Laravel作為在國內(nèi)國外都頗為流行的PHP框架,風(fēng)格優(yōu)雅,其擁有自己的一些特點。
一. 請求周期
Laravel 采用了單一入口模式,應(yīng)用的所有請求入口都是 public/index.php 文件。
注冊類文件自動加載器:Laravel通過composer進行依賴管理,并在bootstrap/autoload.php中注冊了Composer Auto Loader (PSR-4),應(yīng)用中類的命名空間將被映射到類文件實際路徑,不再需要開發(fā)者手動導(dǎo)入各種類文件,而由自動加載器自行導(dǎo)入。因此,Laravel允許你在應(yīng)用中定義的類可以自由放置在Composer Auto Loader能自動加載的任何目錄下,但大多數(shù)時候還是建議放置在app目錄下或app的某個子目錄下
創(chuàng)建服務(wù)容器:從 bootstrap/app.php 文件中取得 Laravel 應(yīng)用實例 $app (服務(wù)容器)
創(chuàng)建 HTTP / Console 內(nèi)核:傳入的請求會被發(fā)送給 HTTP 內(nèi)核或者 console 內(nèi)核進行處理,HTTP 內(nèi)核繼承自 Illuminate\Foundation\Http\Kernel 類。它定義了一個 bootstrappers 數(shù)組,數(shù)組中的類在請求真正執(zhí)行前進行前置執(zhí)行,這些引導(dǎo)程序配置了錯誤處理,日志記錄,檢測應(yīng)用程序環(huán)境,以及其他在請求被處理前需要完成的工作;HTTP 內(nèi)核同時定義了一個 HTTP 中間件列表,所有的請求必須在處理前通過這些中間件處理 HTTP session 的讀寫,判斷應(yīng)用是否在維護模式, 驗證 CSRF token 等等
載入服務(wù)提供者至容器:在內(nèi)核引導(dǎo)啟動的過程中最重要的動作之一就是載入服務(wù)提供者到你的應(yīng)用,服務(wù)提供者負責(zé)引導(dǎo)啟動框架的全部各種組件,例如數(shù)據(jù)庫、隊列、驗證器以及路由組件。因為這些組件引導(dǎo)和配置了框架的各種功能,所以服務(wù)提供者是整個 Laravel 啟動過程中最為重要的部分,所有的服務(wù)提供者都配置在 config/app.php 文件中的 providers 數(shù)組中。首先,所有提供者的 register 方法會被調(diào)用;一旦所有提供者注冊完成,接下來,boot 方法將會被調(diào)用
分發(fā)請求:一旦應(yīng)用完成引導(dǎo)和所有服務(wù)提供者都注冊完成,Request 將會移交給路由進行分發(fā)。路由將分發(fā)請求給一個路由或控制器,同時運行路由指定的中間件
二. 服務(wù)容器和服務(wù)提供者
服務(wù)容器是 Laravel 管理類依賴和運行依賴注入的有力工具,在類中可通過 $this->app 來訪問容器,在類之外通過 $app 來訪問容器;服務(wù)提供者是 Laravel 應(yīng)用程序引導(dǎo)啟動的中心,關(guān)系到服務(wù)提供者自身、事件監(jiān)聽器、路由以及中間件的啟動運行。應(yīng)用程序中注冊的路由通過RouteServiceProvider實例來加載;事件監(jiān)聽器在EventServiceProvider類中進行注冊;中間件又稱路由中間件,在app/Http/Kernel.php類文件中注冊,調(diào)用時與路由進行綁定。在新創(chuàng)建的應(yīng)用中,AppServiceProvider 文件中方法實現(xiàn)都是空的,這個提供者是你添加應(yīng)用專屬的引導(dǎo)和服務(wù)的最佳位置,當然,對于大型應(yīng)用你可能希望創(chuàng)建幾個服務(wù)提供者,每個都具有粒度更精細的引導(dǎo)。服務(wù)提供者在 config/app.php 配置文件中的providers數(shù)組中進行注冊
<?php namespace App\Providers;use Riak\Connection;use Illuminate\Support\ServiceProvider;class RiakServiceProvider extends ServiceProvider { /** * 在容器中注冊綁定 * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection(config('riak')); }); } }
三. 依賴注入
Laravel 實現(xiàn)依賴注入方式有兩種:自動注入和主動注冊。自動注入通過參數(shù)類型提示由服務(wù)容器自動注入實現(xiàn);主動注冊則需開發(fā)人員通過綁定機制來實現(xiàn),即綁定服務(wù)提供者或類(參考: http://d.laravel-china.org/docs/5.4/container )。
綁定服務(wù)提供者或類:這種方式對依賴注入的實現(xiàn)可以非常靈活多樣
use Illuminate\Support\Facades\Storage;use App\Http\Controllers\PhotoController;use App\Http\Controllers\VideoController;use Illuminate\Contracts\Filesystem\Filesystem;$this->app->when(PhotoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('local'); });$this->app->when(VideoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('s3'); });
參數(shù)類型聲明:通過對類的構(gòu)造器參數(shù)類型、類的方法參數(shù)類型、閉包的參數(shù)類型給出提示來實現(xiàn)
<?php namespace App\Http\Controllers;use App\Users\Repository as UserRepository;class UserController extends Controller { /** * user repository 實例。 */ protected $users; /** * 控制器構(gòu)造方法。 * * @param UserRepository $users * @return void */ public function __construct(UserRepository $users) { $this->users = $users; } /** * 儲存一個新用戶。 * * @param Request $request * @return Response */ public function store(Request $request) { $name = $request->input('name'); // } }
路由參數(shù)依賴:下邊的示例使用 Illuminate\Http\Request 類型提示的同時還獲取到路由參數(shù)id
你的路由可能是這樣定義的:Route::put('user/{id}', 'UserController@update');而控制器對路由參數(shù)id的依賴卻可能是這樣實現(xiàn)的:<?php namespace App\Http\Controllers;use Illuminate\Http\Request;class UserController extends Controller { /** * 更新指定的用戶。 * * @param Request $request * @param string $id * @return Response */ public function update(Request $request, $id) { // } }
四. Artisan Console
Laravel利用PHP的CLI構(gòu)建了強大的Console工具artisan,artisan幾乎能夠創(chuàng)建任何你想要的模板類以及管理配置你的應(yīng)用,在開發(fā)和運維管理中扮演著極其重要的角色,artisan是Laravel開發(fā)不可或缺的工具。在Laravel根目錄下運行:PHP artisan list可查看所有命令列表。用好artisan能極大地簡化開發(fā)工作,并減少錯誤發(fā)生的可能;另外,還可以編寫自己的命令。下面列舉部分比較常用的命令:
啟用維護模式:php artisan down --message='Upgrading Database' --retry=60
關(guān)閉維護模式:php artisan up
生成路由緩存:php artisan route:cache
清除路由緩存:php artisan route:clear
數(shù)據(jù)庫遷移 Migrations:php artisan make:migration create_users_table --create=users
創(chuàng)建資源控制器:php artisan make:controller PhotoController --resource --model=Photo
創(chuàng)建模型及遷移:php artisan make:model User -m
五. 表單驗證機制
表單驗證在web開發(fā)中是不可或缺的,其重要性也不言而喻,也算是每個web框架的標配部件了。Laravel表單驗證擁有標準且龐大的規(guī)則集,通過規(guī)則調(diào)用來完成數(shù)據(jù)驗證,多個規(guī)則組合調(diào)用須以“|”符號連接,一旦驗證失敗將自動回退并可自動綁定視圖。
下例中,附加bail規(guī)則至title屬性,在第一次驗證required失敗后將立即停止驗證;“.”語法符號在Laravel中通常表示嵌套包含關(guān)系,這個在其他語言或框架語法中也比較常見
$this->validate($request, [ 'title' => 'bail|required|unique:posts|max:255', 'author.name' => 'required', 'author.description' => 'required',]);
Laravel驗證規(guī)則參考 http://d.laravel-china.org/docs/5.4/validation#可用的驗證規(guī)則 ;另外,在Laravel開發(fā)中還可采用如下擴展規(guī)則:
自定義FormRequest (須繼承自 Illuminate\Foundation\Http\FormRequest )
Validator::make()手動創(chuàng)建validator實例
創(chuàng)建validator實例驗證后鉤子
按條件增加規(guī)則
數(shù)組驗證
自定義驗證規(guī)則
六. 事件機制
Laravel事件機制是一種很好的應(yīng)用解耦方式,因為一個事件可以擁有多個互不依賴的監(jiān)聽器。事件類 (Event) 類通常保存在 app/Events
目錄下,而它們的監(jiān)聽類 (Listener) 類被保存在 app/Listeners
目錄下,使用 Artisan 命令來生成事件和監(jiān)聽器時他們會被自動創(chuàng)建。
注冊事件和監(jiān)聽器:EventServiceProvider的 listen 屬性數(shù)組用于事件(鍵)到對應(yīng)的監(jiān)聽器(值)的注冊,然后運行 php artisan event:generate將自動生成EventServiceProvider中所注冊的事件(類)模板和監(jiān)聽器模板,然后在此基礎(chǔ)之上進行修改來實現(xiàn)完整事件和監(jiān)聽器定義;另外,你也可以在 EventServiceProvider 類的 boot 方法中通過注冊閉包事件來實現(xiàn)
定義事件(類):事件(類)就是一個包含與事件相關(guān)信息數(shù)據(jù)的容器,不包含其它邏輯
1 <?php 2 3 namespace App\Events; 4 5 use App\Order; 6 use Illuminate\Queue\SerializesModels; 7 8 class OrderShipped 9 {10 use SerializesModels;11 12 public $order;13 14 /**15 * 創(chuàng)建一個事件實例。16 *17 * @param Order $order18 * @return void19 */20 public function __construct(Order $order)21 {22 $this->order = $order;23 }24 }
定義監(jiān)聽器:事件監(jiān)聽器在 handle 方法中接受了事件實例作為參數(shù)
1 <?php 2 3 namespace App\Listeners; 4 5 use App\Events\OrderShipped; 6 7 class SendShipmentNotification 8 { 9 /**10 * 創(chuàng)建事件監(jiān)聽器。11 *12 * @return void13 */14 public function __construct()15 {16 //17 }18 19 /**20 * 處理事件21 *22 * @param OrderShipped $event23 * @return void24 */25 public function handle(OrderShipped $event)26 {27 // 使用 $event->order 來訪問 order ...28 }29 }
停止事件傳播:在監(jiān)聽器的
handle
方法中返回false
來停止事件傳播到其他的監(jiān)聽器觸發(fā)事件:調(diào)用 event 輔助函數(shù)可觸發(fā)事件,事件將被分發(fā)到它所有已經(jīng)注冊的監(jiān)聽器上
1 <?php 2 3 namespace App\Http\Controllers; 4 5 use App\Order; 6 use App\Events\OrderShipped; 7 use App\Http\Controllers\Controller; 8 9 class OrderController extends Controller10 {11 /**12 * 將傳遞過來的訂單發(fā)貨。13 *14 * @param int $orderId15 * @return Response16 */17 public function ship($orderId)18 {19 $order = Order::findOrFail($orderId);20 21 // 訂單的發(fā)貨邏輯...22 23 event(new OrderShipped($order));24 }25 }
隊列化事件監(jiān)聽器:如果監(jiān)聽器中需要實現(xiàn)一些耗時的任務(wù),比如發(fā)送郵件或者進行 HTTP 請求,那把它放到隊列中處理是非常有用的。在使用隊列化監(jiān)聽器,須在服務(wù)器或者本地環(huán)境中配置隊列并開啟一個隊列監(jiān)聽器,還要增加 ShouldQueue 接口到你的監(jiān)聽器類;如果你想要自定義隊列的連接和名稱,你可以在監(jiān)聽器類中定義
$connection
和$queue
屬性;如果隊列監(jiān)聽器任務(wù)執(zhí)行次數(shù)超過在工作隊列中定義的最大嘗試次數(shù),監(jiān)聽器的 failed 方法將會被自動調(diào)用1 <?php 2 3 namespace App\Listeners; 4 5 use App\Events\OrderShipped; 6 use Illuminate\Contracts\Queue\ShouldQueue; 7 8 class SendShipmentNotification implements ShouldQueue 9 {10 /**11 * 隊列化任務(wù)使用的連接名稱。12 *13 * @var string|null14 */15 public $connection = 'sqs';16 17 /**18 * 隊列化任務(wù)使用的隊列名稱。19 *20 * @var string|null21 */22 public $queue = 'listeners';23 24 public function failed(OrderShipped $event, $exception)25 {26 //27 } 28 }
事件訂閱者:事件訂閱者允許在單個類中定義多個事件處理器,還應(yīng)該定義一個 subscribe 方法,這個方法接受一個事件分發(fā)器的實例,通過調(diào)用事件分發(fā)器的 listen 方法來注冊事件監(jiān)聽器,然后在 EventServiceProvider 類的 $subscribe 屬性中注冊訂閱者
1 <?php 2 3 namespace App\Listeners; 4 5 class UserEventSubscriber 6 { 7 /** 8 * 處理用戶登錄事件。 9 */10 public function onUserLogin($event) {}11 12 /**13 * 處理用戶注銷事件。14 */15 public function onUserLogout($event) {}16 17 /**18 * 為訂閱者注冊監(jiān)聽器。19 *20 * @param Illuminate\Events\Dispatcher $events21 */22 public function subscribe($events)23 {24 $events->listen(25 'Illuminate\Auth\Events\Login',26 'App\Listeners\UserEventSubscriber@onUserLogin'27 );28 29 $events->listen(30 'Illuminate\Auth\Events\Logout',31 'App\Listeners\UserEventSubscriber@onUserLogout'32 );33 }34 35 }
七. Eloquent 模型
Eloquent ORM 以ActiveRecord形式來和數(shù)據(jù)庫進行交互,擁有全部的數(shù)據(jù)表操作定義,單個模型實例對應(yīng)數(shù)據(jù)表中的一行
1 $flights = App\Flight::where('active', 1)2 ->orderBy('name', 'desc')3 ->take(10)4 ->get();
config/database.php中包含了模型的相關(guān)配置項。Eloquent 模型約定:
數(shù)據(jù)表名:模型以單數(shù)形式命名(CamelCase),對應(yīng)的數(shù)據(jù)表為蛇形復(fù)數(shù)名(snake_cases),模型的$table屬性也可用來指定自定義的數(shù)據(jù)表名稱
主鍵:模型默認以id為主鍵且假定id是一個遞增的整數(shù)值,也可以通過primaryKey來自定義;如果主鍵非遞增數(shù)字值,應(yīng)設(shè)置primaryKey來自定義;如果主鍵非遞增數(shù)字值,應(yīng)設(shè)置incrementing = false
時間戳:模型會默認在你的數(shù)據(jù)庫表有 created_at 和 updated_at 字段,設(shè)置timestamps=false可關(guān)閉模型自動維護這兩個字段;timestamps=false可關(guān)閉模型自動維護這兩個字段;dateFormat 屬性用于在模型中設(shè)置自己的時間戳格式
數(shù)據(jù)庫連接:模型默認會使用應(yīng)用程序中配置的數(shù)據(jù)庫連接,如果你想為模型指定不同的連接,可以使用 $connection 屬性自定義
批量賦值:當用戶通過 HTTP 請求傳入了非預(yù)期的參數(shù),并借助這些參數(shù) create 方法更改了數(shù)據(jù)庫中你并不打算要更改的字段,這時就會出現(xiàn)批量賦值(Mass-Assignment)漏洞,所以你需要先在模型上定義一個 fillable(白名單,允許批量賦值字段名數(shù)組)或fillable(白名單,允許批量賦值字段名數(shù)組)或guarded(黑名單,禁止批量賦值字段名數(shù)組)
1 // 用屬性取回航班,當結(jié)果不存在時創(chuàng)建它...2 $flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);3 4 // 用屬性取回航班,當結(jié)果不存在時實例化一個新實例...5 $flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
模型軟刪除:如果模型有一個非空值 deleted_at,代表模型已經(jīng)被軟刪除了。要在模型上啟動軟刪除,則必須在模型上使用Illuminate\Database\Eloquent\SoftDeletes trait 并添加 deleted_at 字段到你的模型 $dates 屬性上和數(shù)據(jù)表中,通過調(diào)用trashed方法可查詢模型是否被軟刪除
1 <?php 2 3 namespace App; 4 5 use Illuminate\Database\Eloquent\Model; 6 use Illuminate\Database\Eloquent\SoftDeletes; 7 8 class Flight extends Model 9 {10 use SoftDeletes;11 12 /**13 * 需要被轉(zhuǎn)換成日期的屬性。14 *15 * @var array16 */17 protected $dates = ['deleted_at'];18 }
http://www.cnblogs.com/XiongMaoMengNan/p/6644892.html