MaxPHP(原Yao框架)完全開發手冊

chengyao 發表於 2021-05-31

官網: www.chengyao.xyz

要求

PHP >= 7.2.0

如果你需要使用其他功能,例如:快取、資料庫、檢視、Redis、驗證器等等,需要安裝相應元件,環境要求依賴於元件

如果你沒有使用過composer 可以先了解一下這塊的知識 -> 學習筆記

使用Composer安裝:

composer create-project --prefer-dist max/max .

可以用下面的命令安裝開發版

composer create-project --prefer-dist max/max:dev-master .

這行命令會在你命令執行目錄安裝框架

你可以使用Git拉取框架,拉取完成後會自動更新依賴並啟動框架

git clone https://github.com/topyao/max.git . ; php max serve

如果你沒有使用php max serve 命令,你也可以直接在專案目錄使用composer安裝依賴

composer install

安裝完成後就可以使用 php max serve 執行程式。框架強制路由,所以在編寫控制器前應該先定義路由規則,如果你的環境是windows需要修改public/.htaccess中的RewriteRule或者nginx
偽靜態規則,在index.php後面加上?。框架對資料型別比較敏感,例如在該設定為true時候不要設定1。否則會報錯。

偽靜態

下面提供了apachenginx的偽靜態配置

apache

<IfModule mod_rewrite.c>
  Options +FollowSymlinks -Multiviews
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

Nginx

if (!-d $request_filename){
    set $rule_0 1$rule_0;
}
if (!-f $request_filename){
    set $rule_0 2$rule_0;
}
if ($rule_0 = "21"){
    rewrite ^/(.*)$ /index.php/$1 last;
}

注意如果你的環境是windows,可能需要給偽靜態規則中的index.php/後面加上?

這裡的容器主要作用有兩個,實現一些類的單例,實現構造方法、__setter方法、普通方法和閉包的依賴注入

例項化類

使用容器例項化類

$obj = \Max\Facade\App::make($className,$arguments = [],$singleInstance = false);

第一個引數傳入一個完整類名,第二個引數是傳遞給類構造方法的引數列表陣列,第三個引數為true時候表示獲取一個單例,在後面請求中獲取類例項的$singleInstance
true的時候始終不會建立新物件,而是從容器中獲取已經例項化並且依賴注入的物件。

此時$obj是一個給構造方法實現依賴注入的例項,在後面的呼叫例項的方法時候並不會給方法實現依賴注入

可以使用框架提供的app()助手函式,函式可選多個引數,當不傳遞引數的時候會返回app例項,否則第一個引數接受一個字串,容器會例項化該類

方法呼叫

使用容器呼叫例項的方法

\Max\Facade\App::invokeMethod([$className,$method],$arguments = [],$singleInstance = false,$constructorArguments = []);

第一個引數為一個陣列,陣列的第一個元素為需要例項化的類名,第二個元素為要呼叫的方法名。第二個引數為給方法傳遞的引數列表,第三個方法表示例項化的類是不是單例的,第四個引數為例項化類過程中給構造方法傳遞的引數列表

可以使用框架提供的助手函式invoke()

閉包的依賴注入

\Max\Facade\App::invokeFunc(function(){
    //...
},array $arguments);

可以使用框架提供的助手函式invoke()

獲取例項

獲取容器內的例項可以使用get方法

\Max\Facade\App::get($className);

獲取例項可以使用還可以使用make方法,app例項的物件屬性訪問方式,app例項的屬性陣列訪問方式。

判斷例項存在與否

判斷容器中的例項是否存在可以使用

\Max\Facade\App::has($abstract);

繫結類和類的標識

    \Max\Facade\App::bind($id, $className);

後面就可以使用$id 來獲取例項,而不是使用類名,例如app($id) 可以直接取得$id的例項

移除例項

    \Max\Facade\App::remove($className);

顧名思義,可以移除存放在容器中的例項,$className 可以是類的標識,也可以是完整類名

通過標識獲取類名

  \Max\Facade\App::bound($id)

注意:控制器方法是始終實現依賴注入的。

  • app 應用目錄

    • Console 命令列

    • Http

      • Controllers 控制器目錄

      • Middleware 中介軟體目錄

      • Validate 驗證器目錄

      • Controller.php 使用者自定義基礎控制器類

      • Validate.php 驗證器類

    • Models 模型目錄

    • Events 事件目錄

    • Facade 使用者自定義門面目錄

    • common.php 使用者自定義函式檔案

  • config 配置檔案目錄

    • app.php 應用配置檔案

    • cache.php 快取配置檔案

    • database.php 資料庫配置檔案

    • view.php 檢視配置檔案

    • provider.php 服務提供者

  • extend 擴充套件類庫目錄【名稱空間為\】

  • public 應用訪問目錄

    • .htaccess apache偽靜態檔案

    • nginx.conf nginx偽靜態檔案

    • index.php 入口檔案

  • routes 路由目錄

    • api.php api路由

    • web.php web路由檔案

  • vendor 擴充套件包(包含框架核心)

  • views 檢視目錄

  • .env 環境變數檔案

  • .example.env 環境變數示例檔案

  • .htaccess 偽靜態檔案

  • composer.json composer配置檔案

  • composer.lock composer鎖定檔案

  • LICENSE 開源許可證

  • README.md

  • DOCUMENT.md

  • CHANGELOG.md

  • max 命令列檔案

框架對單/多應用這個概念比較模糊,只是在定義路由和渲染模板的時候應該有所注意,這裡在下面的章節中會提到。

配置檔案包含兩種,一種是config目錄下的以小寫字母開頭的.php為字尾的檔案,另一種是框架根目錄下的.env檔案,下面簡單介紹下如何使用他們。

ENV

在開發環境下大多數配置都可以通過.env檔案獲取,而且預設為從.env檔案獲取,線上環境需要刪除.env檔案或者將配置中的env去掉,例如在app.php
中有這樣'debug' => env('app.debug', false),一個配置,我們可以更改為'debug' => false, .env檔案可以使用節,例如:

[APP]
DEBUG=true #開啟除錯
AUTO_START=true 

其中app就是一節,獲取DEBUG配置可以使用env('app.debug')或者\Max\Facade\Env::get('app.debug');

config

配置檔案是位於config目錄下,以.php結尾的返回一個關聯陣列的檔案。

獲取所有配置使用

\Max\Facade\Config::get();

可以傳入一個引數例如app,則會獲取app.php檔案中的配置,傳入app.auto_start 則獲取app中的auto_start引數的值

如果需要自定義一個配置檔案,可以在/config目錄下新建例如alipay.php檔案並返回一個陣列。

\Max\Facade\Config::get('alipay.param');       //獲取配置

可以使用輔助函式config() ,例如config('app.debug')

Facade基本程式碼示例如下:

<?php

namespace App\Index\Facade;

use Max\Facade;

class UserCheck extends Facade
{
    protected static function getFacadeClass()
    {
        return \App\Index\validate\UserCheck::class;
    }
}

你可以在任何可以composer自動載入的位置建立類並繼承Max\Facade類,就可以實現靜態代理,但是為了方便維護,建議建立在應用對應的facade目錄下。

注意: Facade預設例項化的物件都是會儲存在容器中的。如果不需要儲存,可以加入protected static $singleInstance = false;,當然僅僅是在你的請求的頁面中使用該類的方法全部為Facade或者依賴注入或者容器獲取的例項的時候才是最早例項化的類。

Facade還有一個屬性,protected static $methodInjection = false;當為true的時候該門面呼叫的類支援對普通方法的依賴注入

服務實現基本程式碼如下

<?php

namespace App\Index\Services;

use \Max\Foundation\App; 

class Test implements Service
{
    public function register(){
        app()->bind('test', \Test::class);
    }
    public function boot()
    {
        echo '1';
    }
}

定義如上服務類,並將類註冊到/config/app.php中的provider中,這樣在app啟動的時候會首先呼叫register方法註冊服務,註冊完成後立即呼叫boot方法。上面的程式碼註冊了Test
的服務,當app啟動會先向容器中繫結test類,然後會呼叫boot方法。

路由存放的檔案有兩個web.php , api.php 噹噹前請求方式是ajax的時候只會註冊並匹配api.php中的規則,否則只會註冊並匹配web.php中的路由

注意:需要引入\Max\Facade\Route

路由定義

路由的定義方式有三種:字串,陣列,閉包

路由定義需要設定請求方式例如

Route::get('路由地址','路由表示式');   //get方式請求的路由  
Route::post('路由地址','路由表示式');  //post方式請求的路由

請求方式可以是get,post,put,delete,patch等請求型別,以下非特殊都是用get做演示,這裡的路由地址是不包含queryString的,即使url中有queryString,也會匹配該路由。

字串

當我們使用單應用模式的時候,按照下面的方法定義路由

Route::get('路由地址','控制器@方法');

例如

Route::get('index','index/[email protected]'); 

這裡的index/[email protected]@後的字串為呼叫的方法名,前面的組成類似App\Http\Controllers\Index的類名,對應到目錄中為/app/Http/Controllers/index.php
這樣就很容易理解如何建立單、多應用。只需給路由表示式新增多個斜線分割,對應於類所處的資料夾上下級。

陣列

使用陣列的方式定義路由,陣列的第一個引數必須是一個控制器類的完整類名,第二個引數為方法名字串,例如

Route::get('index',['\App\Http\Controllers\Index','index']);

表示對映到\App\Http\Controllers\Index控制器的index方法

閉包

Route::get('index',function(){
       return view('模板檔案');
});

注意:這裡使用到了view助手函式,當路由地址中含有引數時可以給閉包函式傳遞相應引數,在下面會提到。

路由高階

多請求型別路由

當我們一個url需要多種請求方式來訪問的時候可以定義rule型別的路由,例如:(這裡的/非必須,但是建議加上)

Route::rule('/', 'index/[email protected]', ['get', 'post']);

第三個引數傳入請求方式陣列,可以為空,為空預設為getpost

正規表示式與引數傳遞

在上面提到了路由是可以給控制器方法或者閉包傳遞引數的。

例如我定義了一個如下的路由

Route::get('/article/index(\d+)\.html', 'index/[email protected]');

該路由的第一個引數是一個不帶定界符的正規表示式,該表示式會匹配/article/index任意數字.html的請求地址,這個正則中使用了一個匹配組(\d+),並且這個組是第一次出現的,那麼就可以在控制器方法或者閉包中傳入一個引數。

給閉包傳參

Route::get('/article/index(\d*)\.html',function($id = 0){
    echo $id;
});

注意:這裡的閉包是可以實現依賴注入的

給控制器方法傳參

public function read($id = 0){
    echo $id;
}

可以傳入多個引數,匹配組出現的順序就是傳遞給方法或者閉包的引數順序,例如:

Route::get('/(\w+)-index(\d+)\.html',function($a,$b){
    echo $a,$b;
});

訪問blog-index2.html 時會輸出blog2

注意:正則路由中的正則不需要新增定界符,多個引數是按匹配到的順序傳遞的。轉義符號務必使用反斜線,否則url助手函式可能不能正確獲取到正則路由的地址

路由支援註冊別名,例如

Route::get('/','index/[email protected]')->alias('index');

之後就可以在任意位置使用url助手函式獲取路由地址,例如url('index') 返回/,如果url() 函式中傳入的引數並沒有被註冊別名,那麼會原樣返回。url函式可以新增第二個引數來給正則路由傳遞引數,例如

Route::get('/b(.*)\.html','index/[email protected]')->alias('blog');

此時可以使用url('blog',[1]); 生成的url地址為/b1.html ,這裡url的第二個引數為一個索引陣列,引數按照在陣列中的順序傳遞。

路由可以設定快取

快取目前因為一個重大問題暫時不要使用,當路由中不存在閉包時候沒有影響

php max route   //根據提示選擇選項

設定快取檔案後路由不會再通過呼叫/route下檔案中的大量方法來註冊,而是直接從快取檔案中讀取,所以在開發環境上建議不要使用路由快取,否則新增或刪除路由不能及時更新

其他規則路由

None路由

使用

Route::none(function(){
    //return view('index/index');
},$data = []);

建立一個none路由,當所有路由未匹配到時會匹配該路由,需要給第一個引數傳入一個閉包,第二個引數可選地傳入一個索引陣列,陣列的每一個值都會按照陣列的索引順序傳入閉包中,閉包中需要有相應形參或其他方式來獲取傳值。

檢視路由

Route::view('index','index/index',['get']);

該路由表示get方式請求的/index會被對映到views目錄下的index目錄下的index.html模板檔案,分隔符後最後的部分為模板檔名,前面均為目錄名。最後一個引數為可選引數,為空預設為get
方式請求的路由;

重定向路由

Route::redirect('index','https://www.1kmb.com',302,['get']);

該路由表示get方式請求的/index會被重定向到https://www.1kmb.com。後兩個引數為可選引數,第一個為跳轉狀態碼,預設為302;第二個為請求方式,預設為[‘get’];

跨域支援

框架支援跨域功能,在定義路由的時候可以設定跨域,可以設定全域性跨域,只需要更改配置檔案中的app.php中的middleware中加上\Max\Http\Middleware\GlobalCross::class中介軟體即可

Route::get('/','index/index/index')->cors('*'); 

注意:這裡cors() 方法的引數可選,引數一:$AllowOrigin 允許跨域域名,可以設定一個’*’或者字串完整url或者陣列的完整url,引數二:$AllowCredentials 是否可以將對請求的響應暴露給頁面,引數三:$AllowHeaders 允許的頭資訊,引數四Maxage預檢快取有效期

獲取請求引數

獲取請求可以用Facade

\Max\Facade\Request::get()

如果需要獲取某一個引數,可以使用

\Max\Facade\Request::get('a');

可以給第二個引數傳入一個預設值,例如

\Max\Facade\Request::get('a','default');

獲取多個引數可以使用

\Max\Facade\Request::get(['a','b']);

可以傳入一個關聯陣列,陣列的鍵為引數名,值為預設值,例如

\Max\Facade\Request::get(['a' => 1,'b' => 2]);

此時如果a不存在,則a的值為1

獲取post請求的內容

\Max\Facade\Request::post();

獲取原始資料

\Max\Facade\Request::input();

獲取所有$_REQUEST使用

\Max\Facade\Request::param();

post和param使用方法和get一樣。可以給這些方法新增第二個引數,第一個引數為字串且不存在的時候會返回預設引數

獲取$_SETVER 變數

替代地,可以使用Request::server($name) 獲取$_SERVER中的值,如果不存在返回null

獲取header

可以使用Request::header(); 獲取所有header資訊,可以傳入一個引數,例如Request::header('user_agent');獲取UA

判斷請求型別

使用isMethod方法判斷任何請求型別,例如判斷請求型別是否為get

\Max\Facade\Request::isMethod('get');

還可以判斷是否是ajax請求

\Max\Facade\Request::isAjax() 

可以使用基礎控制器

當控制器繼承了基礎控制器App\Http\Controller或者\Max\Http\Controller後就可以直接使用

$this->request->get();

的方式獲取引數,其他用法和Facade類似

請求快取

請求快取可以在路由中配置,只需要在註冊路由中使用連貫操作呼叫cache()方法,傳入一個整數,表示請求快取的時間/秒,例如:

Route::get('index','index/index')->cache(600);

表示該請求可能會快取600

引數過濾

請求是可以設定函式進行過濾的,可以在app.php中的filter陣列中新增過濾函式,注意函式必須只能傳入一個引數,並且返回過濾後的字串。如果使用Request類獲取引數預設是被過濾的。不需要過濾可以使用$_GET陣列。

注意:如果需要獲取的引數不存在,該引數的值將會是null,例如Request::get(['a','b'])當b不存在的時候會是null,此時需要用is_null判斷。

支援全域性,路由,控制器前後置中介軟體

執行大概流程: 請求 -> App啟動 -> 全域性中介軟體 -> 路由註冊 -> 路由中介軟體 -> 路由分發 -> 控制器中介軟體 -> 控制器 -> 控制器中介軟體 -> 路由中介軟體 -> 全域性中介軟體 -> 響應傳送

首先需要建立一箇中介軟體,例如

<?php

namespace App\Http\Middleware;

use Max\Facade\Session;

class Login
{
    public function handle($request, \Closure $next)
    {
        if(!Session::get('user')){
            view('index/404');
            exit;
        }
        $response = $next($request);
        echo '執行完了’;
        return $response;
    }
}

注意:$next($request) 之後其實大部分程式碼已經被執行了,所以如果你需要在執行前中斷,需要在$next($request)前呼叫exit或者die。這裡的$request是請求例項,可以直接新增引數例如$request->id = 1

全域性中介軟體

app.php配置檔案中middleware中配置的中介軟體為全域性中介軟體

控制器中介軟體

在控制器中新增屬性

public $middleware = [
    \App\Http\Middleware\Login::class => ['edit'],
];

表示控制器中的方法edit會使用Login中介軟體

在這個請求中如果獲取不到session中的user,就會渲染檢視404,不會向下執行,如果可以獲取user,那麼向下執行,執行控制器方法,執行完畢後再輸出’執行完了’

注意:如果你需要控制器中可以被直接請求到的方法全部使用某一個控制器中介軟體可以這樣寫\App\Http\Middleware\Login::class => '*'

路由中介軟體

可以使用middleware方法註冊一個路由中介軟體,例如

Route::get('index','index/index')->middleware('\\App\\Http\\Middleware\\Login::class);

不管路由中註冊的是閉包還是類名,都會經過中介軟體,目前的中介軟體實現很low所以不要在中介軟體中return $next($request);

在控制器中可以直接return一個陣列,框架會自動轉為json輸出,例如resopnse(array $data,202,['Content-Type:application/json']);
第一個引數為資料,第二個為狀態碼,第三個為頭資訊。

要使用驗證器,需要安裝驗證器元件

   composer require max/validator:dev-master

以下文件沒有更新,以實際使用為準。使用throwAble方法可以設定是否丟擲異常
需要驗證的資料必須是陣列,比如通過Request類方法傳入陣列獲取的陣列。

基礎驗證器

public function test()
{
   $data = Request::post();
   $vali = Max\Facade\Validate::rule([
       'username' => ['required' => true, 'max' => 10, 'regexp' => '\w+']
   ])->check($data);
   if (true !== $vali) {
       exit($vali);
   }
}

驗證器操作必須按照如上程式碼寫,可以在App\Validate類中新增方法例如_checkUservali
,驗證成功返回true,失敗將訊息新增到成員屬性$message陣列後返回false。之後使用rule方法的時候就可以使用rule([‘username’ => [‘uservali’ => 1])
;驗證username欄位。當一個欄位驗證失敗後就不會再驗證其他欄位了! 驗證器支援全部驗證,只需要給check方法的第二個引數傳入true即可開啟全部驗證,非批量驗證失敗返回訊息字串,批量驗證失敗返回訊息索引陣列。

預設可用的驗證器有max,min,length,enum,required,regexp,bool,confirm

_checkBool 當值為'on', 'yes', 'true', true, 1, '1'時為真,相反為假,在驗證規則中應該傳入true或者false 在驗證regexp
的時候需要編寫完整驗證正規表示式包括定界符,例如:/\[email protected]\w+\.\w{3}/i 注意這裡驗證使用了preg_match,所以在編寫正規表示式的時候應該注意,例如不要使用模式修正符g

獨立驗證

新增了獨立驗證,你可以在任何可以composer自動載入的位置新增驗證器類例如UserVali,並繼承App\Validate,在該類中新增驗證規則$rule

protected array $rule = [
    'username' => ['required' => true]
];

可以使用助手函式validate()進行驗證

validate($data, UserVali::class);

以下文件沒有更新,不要參考

第一個引數為需要驗證的資料,第二個引數為驗證器類名完整字串,注意這裡追加的規則時使用+語法將兩個陣列合並,可能導致覆蓋,獨立驗證可以設定屬性$checkAll用來設定是否是全部驗證,當$checkAll
為true時開啟批量驗證,否則一旦有驗證失敗的條目都會結束驗證。獨立驗證可以使用連貫操作和追加刪除操作,例如

$vali = $this->validate(UserVali::class,$data)->min(['a' => 1])->remove(['password' => ['required']])->append(['password' => ['min' => 1]])->check();

驗證器隨意增加或者刪除驗證規則,例如:

Validate::rule(['a' => ['required' => true])->append(['a' => ['max' => 2,'min' => 1]])->append(['b' => ['required' => true])->remove('a')->remove(['a' => ['required','max'])->remove(['a' => 'min'])->check($data);

驗證器還可以使用連貫操作

$vali = Validate::data($data)->max(['a' => 10])->required(['a' => true,'b' => true)->check();

或者使用

(new Validate($data))->max('a',10)->check();

或者使用

(new Validate())->max('a',10)->check($data);

注意:這的Validate可以是任意你新建的繼承了App\Validate或者\Max\Validate
的類,只是前者會包含你自定義的驗證規則,後則會不包含,並且如果在你的驗證器類中存在rule屬性的設定就不再需要傳入rule規則了,直接使用check即可。如果驗證成功會返回true,否則返回帶有錯誤資訊的陣列,使用閉包驗證時func方法第一個引數傳入要驗證的欄位,第二個引數傳入閉包,第三個引數可選傳入傳遞給閉包的引數列表陣列。

驗證提示

可以自定義驗證規則的提示,只需要給屬性notice設定和驗證規則類似的陣列,並且將驗證的限定值改為提示資訊即可。

驗證器支援設定驗證失敗丟擲異常,只需將獨立驗證的屬性throwAble設定為true,或者給check方法傳入第三個引數true,即可開啟丟擲異常,批量驗證失敗丟擲異常資訊為json。

框架驗證器內建諸多規則

required 引數必須 max min length regexp bool in confirm

假如我定義了以下路由

Route::get('/','index/index/index');

如果需要編寫控制器程式碼,就需要編寫/app/Http/Controllers/Index目錄下的Index.php控制器裡的index方法

控制器的基本程式碼如下:

<?php

namespace App\Http\Controllers\Index;

class Index
{
    public function index()
    {
    }
}

控制器可以繼承\App\Http\Controller 基礎控制器來使用基礎控制器中提供的方法,你也可以自定義基礎控制器

可以給控制器方法傳入引數,引數個數和位置取決於路由中正則匹配到的引數。 當路由中的引數為可選,就應該給控制器引數一個初始值

如果你繼承了基礎控制器,那麼會有兩個屬性可以提供使用,$this->request,$this->app ,分別時請求物件和app物件,app物件是來管理容器中例項的,使用方法如下:

$this->app['完整類名'];

這是會直接返回該類的例項,並且其構造方法是實現依賴注入的,如果該類是單例的,並且使用

$this->app->has('完整類名');

返回true,那麼,例如該類繫結的標識為request,可以直接使用$this->app->request獲取容器中的例項。

當繼承了基礎控制器後不再建議使用建構函式初始化,而是使用init() 方法進行初始化。

public function init(){}

模型的目錄在app\Models下,新建模型繼承Max\Database\Model類即可使用模型提供的方法。模型名為表名,也可以在模型中設定name屬性,此時的表名就是name的值。
例如我新建了一個Notes的模型,可以在模型中直接使用 $this->where([‘name’ => ‘cheng’])->select() 進行查詢

初始化

當類繼承了Max\Database\Model類後就不要再使用建構函式初始化了,而是採用init方法進行初始化

要使用檢視需要安裝檢視元件

composer require max/view:dev-master

或者安裝其他檢視元件

使用內建模板驅動

模板引擎可以使用twig或者smarty,可以在config/view.php中設定模板引擎。

注意:需要手動改安裝對應模板引擎;

檢視目錄位於根專案目錄下views資料夾,可以使用助手函式渲染模板

view('index/index');

這裡的第一個引數和控制器解析規則類似,表示/views/index/index.html 模板檔案,這裡的模板字尾可以在/config/view中修改suffix 選項

模板渲染方法可以傳入第二個陣列引數用來給模板賦值,例如

view('index',['data'=>$data]);

或者使用Facade

\Max\Facade\View::render('index',$params);

你可以使用composer安裝你喜歡的模板引擎

自定義驅動

框架允許你自定義任何檢視驅動,可以在任何可以composer自動載入的位置定義檢視驅動,並且在檢視配置view.php中將type和檢視配置名改為你的檢視驅動完整類名。

檢視驅動需要繼承\Max\View\Driver.php 並且實現public function render($params){} 和init方法。繼承該類後可以使用$this->template
獲取需要渲染的模板檔名。使用方法可以參考內建的檢視驅動。

Db類目前已經從框架分離 文件

Max-Database 旨在輕量簡單易用的資料庫操作,使用者不需要掌握太多SQL語言就可以實現增刪改查

提供了下面兩種操作方法,本質是相同的。


//門面

\Max\Facade\Db::name('users')->select()

//依賴注入

public function index(\Max\Database\Query $query) {

$query->name('users')->select();

}

該元件依賴於MaxPHP,Max-Framework,所以需要先安裝MaxPHP


composer create-project max/max .

如果你已經安裝,但是卻沒有安裝Max-Database,需要使用下面的命令安裝


composer require max/database

安裝完成後自動會將資料庫配置檔案database.php移動到框架的config目錄下,如果沒有移動則需要手動建立,配置檔案例項如下


<?php

return [

//預設資料庫配置

'default' => env('database.default', 'mysql'),

'mysql' => [

//如果有這項會優先使用DSN

'dsn' => '',

//主機地址

'host' => env('database.host', 'localhost'),

//資料庫使用者名稱

'user' => env('database.user', 'user'),

//資料庫密碼

'pass' => env('database.pass', 'pass'),

//資料庫名

'dbname' => env('database.dbname', 'dbname'),

//埠

'port' => env('database.port', 3306),

//額外設定

'options' => env('database.options', [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]),

//編碼

'charset' => env('database . charset', 'utf8mb4'),

//資料表字首

'prefix' => ''

],

]

目前支援MySQL,PostgreSQL

users表中新增一條資料

\Max\Facade\Db::name('users')->insert(['name' => 'username','age' => 28]);

\Max\Facade\Db::name('users')->where('id > 10')->delete();

刪除id大於10的使用者。
id大於10users表中的資料中sex欄位全部更新為boy

\Max\Facade\Db::name('users')->where('id > 10')->update(['sex' => 'boy']);

條件構造主要有以下幾個方法:table,name,fields,where,whereOr,whereIn,whereNotIn,whereLike,whereExists,whereBetween

,whereNull,whereNotNull,order,group,join,leftJoin,rightJoin,limit

table


table(string $table)

如果有字首則$table必須加上字首

name


name(string $table)

如果有字首,則不需要加字首

fields


fields($fields)

設定要查詢的欄位,可以是索引陣列,也可以是字串,不使用該方法預設為*

order


order(array $order)

\Max\Facade\Db::name('users')->order(['id' => 'DESC','sex' => 'DESC'])->select();

最終的SQL可能是


SELECT * FROM users ORDER BY id DESC, sex DESC;

group


group(array $group)

\Max\Facade\Db::name('users')->group(['sex','id' => 'sex = 1'])->select();

最終的SQL可能是


SELECT * FROM users GROUP BY sex,id HAVING sex = 1;

limit


limit(int $limit, int $offset = null)

\Max\Facade\Db::name('users')->limit(1,3)->select();

\Max\Facade\Db::name('users')->limit(1)->select();

根據資料庫不同最終的SQL可能是


SELECT * FROM users LIMIT 3,1;

SELECT * FROM users LIMIT 1;

也可能是


SELECT * FROM users LIMIT 1 OFFSET 3;

join

聯表有提供了三種方式innerJoin leftJoin rightJoin

例如如下語句:


\Max\Facade\Db::name('users')->join(['books' => 'books.user_id = users.id'])->select();

\Max\Facade\Db::name('users')->leftJoin(['books' => 'books.user_id = users.id'])->select();

\Max\Facade\Db::name('users')->rightJoin(['books' => 'books.user_id = users.id'])->select();

最終的SQL可能是


SELECT * FROM users INNER JOIN books on books.user_id = users.id;

SELECT * FROM users LEFT JOIN books on books.user_id = users.id;

SELECT * FROM users RIGHT JOIN books on books.user_id = users.id;

where


where(array $where, string $operator = '=')

例如我有如下的查詢


\Max\Facade\Db::name('users')->where(['id' => 1, 'sex = 0'])->select();

\Max\Facade\Db::name('users')->where(['id' => 2], '>=')->select();

最終的SQL可能依次如下


SELECT * FROM users WHERE id = ? AND sex = 0;

SELECT * FROM users WHERE id >= ?;

可以看到id = ?sex = 0 說明id這個條件可以經過預處理的,而條件陣列的鍵為數字的卻不會被處理。

whereLike


whereLike(array $whereLike)

例如我有如下的查詢


\Max\Facade\Db::name('users')->whereLike(['username' => 1, 'sex = 0'])->select();

最終的SQL可能如下


SELECT * FROM users WHERE username LIKE ? AND sex = 0;

查詢一條可以用get方法

查詢users表中id為1的一條資料,通常要配合條件語句定位資料


\Max\Facade\Db::name('users')->where(['id' => 1])->get()

查詢某一個值

查詢users表中的id2username


\Max\Facade\Db::name('users')->where(['id' => 2])->value('username');

總數查詢

查詢users表的總資料,返回int


\Max\Facade\Db::name('users')->count();

count()方法可以傳入一個引數即列名,不傳預設為*

查詢多條可用select方法

查詢users表中id在1,2,3範圍內的2條,其偏移量為3


\Max\Facade\Db::name('users')->field('id')->whereIn(['id' => [1,2,3]])->limit(2,3)->select();

查詢到的是資料集物件,可以使用toArray或者toJson獲取,例如


\Max\Facade\Db::name('users')->limit(1)->select()->toArray();

查詢某一列值

查詢users表中的username


\Max\Facade\Db::name('users')->column('username');

$res = \Max\Database\Db::transaction(function (Query $query, \PDO $pdo) {

//$pdo->setAttribute(\PDO::ATTR_ORACLE_NULLS,true); 可以自行設定需要的引數

$deletedUsers = $query->name('users')->whereIn(['id' => [1,2,3]])->delete();

if(0 == $deletedUsers){

throw new \PDOException('沒有使用者被刪除!');

}

return $query->name('books')->whereIn(['user_id' => [1,2,3]])->delete();

});

其中transaction接受一個閉包的引數,該回撥可以傳入兩個引數,一個是當前的查詢例項,另一個是PDO例項,可以看到這裡執行了兩條SQL

,當執行結果不滿足時可以手動丟擲PDOException異常來回滾事務,否則如果執行過程丟擲異常也會自動回滾事務。執行沒有錯誤結束後提交事務。該閉包需要返回執行的結果,返回的執行結果會被transaction方法返回。
替代地,可以使用queryexec方法來執行SQL。一般地,query對應查詢,exec對應增刪改

query


\Max\Facade\Db::query('SELECT * FROM users WHERE id > ?', [10], true);

第一個引數為SQL字串,可以包含?或者:id類似的佔位符,第二個引數對應要繫結到SQL上的引數,第三個為true會查詢全部,否則只取出一條。


\Max\Facade\Db::exec('DELETE FROM users WHERE id > ?', [10]);

上面的執行結果為刪除users表中id大於10的所有資料
當我們編寫好程式碼之後往往需要檢視最終執行的SQL,這時候Max-Database 提供了一個方法getSQL() 在最終執行前呼叫該方法,會將SQL列印出來例如:


\Max\Database\Db::name('users')->where(['id' => 1], '>=')->getSQL()->select();

無論SQL執行是否出錯都可以使用上面的方法。如果執行結果返回的是資料集,例如get(),select()方法,執行成功後也可以呼叫getSQL()方法來獲取SQL,也可以使用getBindParmas()

方法獲取繫結的引數。

注意:你可以自行安裝medoothink-orm等資料庫操作類庫或者使用自帶的Db類,該Db類的操作方法大部分需要的是陣列型別的引數。
開發版本可以檢視整個請求生命週期中所有查詢的SQL語句

可以使用門面的方式


\Max\Facade\Db::getHistory();

或者直接使用Query類

public function index(Max\Database\Query $query){

\Max\Facade\Db::name(‘users’)->where([‘id’ => 1], ‘>’)->select();

halt($query->getHistory());

}

會返回一個二維陣列,包含每條SQL和SQL執行時間

使用快取需要安裝快取元件

composer require max/cache:dev-master

快取元件支援file,memcached,redis

使用

安裝完成後可以使用快取的門面,例如

    \Max\Facade\Cache::get($key);
    \Max\Facade\Cache::set($key,$value,$timeout = null);

也可以使用cache() 助手函式,該函式返回Cache 例項,可以使用如下方法

    cache()->get($key);
    cache()->set($key,$value,$timeout = null);

需要使用更豐富的Redis操作需要安裝Redis元件

composer require max/redis:dev-master

該擴充套件不要求使用MaxPHP,你可以在任何地方使用,僅作為一個擴充套件。支援單、多臺redis,支援讀寫分離

具體使用方法可以檢視redis 擴充套件的README.md介紹

框架提供了一個簡單的Basic認證中介軟體\App\Http\Middleware\BasicAuth::class,可以在app.php配置檔案中新增該中介軟體,新建配置檔案auth.php,檔案內容如下

<?php

return [
    'basic' => [
        'idac' => 'user',
        'user' => 'pass'
    ]
];

注意:如果你使用了apache,那麼需要在配置檔案中加入SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0

halt()

除錯使用助手函式halt()可以傳入多個要除錯的變數,除錯結束會終止指令碼。

abort()

異常丟擲

view()

檢視渲染

response()

響應

url()

獲取別名註冊的url

框架提供了不豐富的命令操作,目前支援路由列表,路由快取,啟動內建服務等操作;只需要在專案目錄下開啟命令視窗輸入以下指令就可以方便地進行各種操作。

php max        //所有命令的幫助
php max serve  //會提示輸入一個埠來建立服務,預設為8080
php max route  //會提示輸出列表或者路由快取操作,根據提示輸入數字即可

聯絡郵箱:[email protected],感謝:PHPStrom

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章