本文適用於 Laravel 5.0 以上版本。

什麼是 Route Model Binding?

Laravel model binding provides a convenient way to inject class instances into your routes. For example, instead of injecting a user's ID, you can inject the entire User class instance that matches the given ID. Reference

中文版:

Laravel 模型綁定提供方便的方式將模型實例注入到你的路由中。例如,比起注入 User 的 ID ,你可以選擇注入符合給定 ID 的 User 類別實例。

文字敘述不懂沒關係,更快的方式就是舉個例子,假設我們有一個 Resource Route 及對應的 Resource Controller:

Route::resource('articles', 'ArticlesController');
class ArticlesController extends Controller
{
// 省略七個標準 RESTful method
}

一般來說,在 show method 裡我們通常會這樣實作:

public function show($id)
{
$article = Article::find($id);
return view('articles.show', compact('article'));
}

但是只要透過 Route Model Binding,我們的程式碼就可以改成這樣:

public function show(Article $article)
{
return view('articles.show', compact('article'));
}

對於我這種超懶的開發者很受用,少寫一行算一行,幫助開發更快速。

設定 Route Model Binding

綁定 Model

一般來說都會將綁定設定在 RouteServiceProvider(App/Provider/RouteServiceProvider.php)中,在這裡我用上述的範例做綁定:

public function boot(Router $router)
{
parent::boot($router);
$router->bind('articles', 'App\Article');
}

接著在我們的 method 直接使用 type-hine 注入 Model,就可以直接存取 $article 了:

public function show(Article $article)
{
return view('article.show', compact('article'));
}

也就是說,如果 Request 是 /articles/7,那麼 $article 就會是 Article::findOrFail(7),若該筆資料不存在則會拋出 404。

綁定做了什麼?

那麼 bind 做了什麼事呢?讓我們看一下 Route list:

+-----------+---------------------------+------------------+----------------------------+
| Method | URI | Name | Action |
+-----------+---------------------------+------------------+----------------------------+
| GET|HEAD | articles | articles.index | ArticlesController@index |
| GET|HEAD | articles/create | articles.create | ArticlesController@create |
| POST | articles | articles.store | ArticlesController@store |
| GET|HEAD | articles/{articles} | articles.show | ArticlesController@show |
| GET|HEAD | articles/{articles}/edit | articles.edit | ArticlesController@edit |
| PUT | articles/{articles} | articles.update | ArticlesController@update |
| PATCH | articles/{articles} | articles | ArticlesController@update |
| DELETE | articles/{articles} | articles.destroy | ArticlesController@destroy |
+-----------+---------------------------+------------------+----------------------------+

注意到有 {articles} 的 Route,這邊的變數 articles 也就是我們在 bind()傳入的第一個參數,Route Model Binding 會自動在你綁定的 Model(第二個參數 \App\Article) 搜尋(findOrFail)主鍵為 {articles} 的資料。所以不只在 show method,只要任何有 {articles} 的 Route 都會自動做綁定,相當的方便(懶人)。

自定搜尋條件

有些情況並不適用於預設的 Model::findOrFail($id),例如只希望找出已經發佈的 Article,這時候可以改變 bind() 的第二個參數為包含自訂搜尋的條件的 Closure:

public function boot(Router $router)
{
parent::boot($router);
$router->bind('articles', function ($id) {
return \App\Article::where('published_at', '<=', Carbon::now())->findOrFail($id);
});
}

到此你已經瞭解如何運用 Route Model Binding 囉!未來如果搭上 Form Model binding 在開發上會更加的快速(懶人)!

← Back to Home