Laravel 學習筆記(11) - Route 進階

Route 進階

在微型部落格專案中,我們的 routes.php 內容是這樣:
Route::get('post', 'HomeController@index');
Route::get('post/create', 'HomeController@create');
Route::post('post', 'HomeController@store');
Route::get('post/{id}', 'HomeController@show');
Route::get('post/{id}/edit', 'HomeController@edit');
Route::put('post/{id}', 'HomeController@update');
Route::delete('post/{id}', 'HomeController@destroy');
目前只有一個編輯文章的功能。假如你的網站功能很多,Route 肯定會多到難以維護,其實有幾個方法可以加以調整,本節將專注在 Route 的使用上。

群組化(group)

你會注意到,這些功能全都在 post 這個網址之下,因此我們可以將它往上提,改成這樣:
Route::group(['prefix'=>'post'], function(){
    Route::get('/', 'HomeController@index');
    Route::get('create', 'HomeController@create');
    Route::post('/', 'HomeController@store');
    Route::get('{id}', 'HomeController@show');
    Route::get('{id}/edit', 'HomeController@edit');
    Route::put('{id}', 'HomeController@update');
    Route::delete('{id}', 'HomeController@destroy');
});
使用 Route::group 將位於同一名稱底下的網址群組化。['prefix'=>'post'] 的 prefix 是關鍵字,用來指定前置字 post,因此,原本 route 中的 post 就可以移除或改成斜線。如此在管理上就能很清楚的看到,它們是一夥的。

除了 prefix 關鍵字外,還有 beforeafter 等可以使用。

資源控制器(Resource controllers)

這裡要先到終端機(Terminal)看一下我們現在的 route 表。使用 cd 指令進入 blog 網站目錄,輸入:
php artisan routes
會列出目前所建立的 route 表: 現在我們要透過 Route::resource 的方式來換掉前面寫了七行的 route:
Route::resource('post', 'HomeController');
記得把前面的七行 route 刪掉(或註解掉),存檔後再次在終端機執行同樣的指令,你會得到幾乎相同的 routing 表: 多了一行 PATCH,功能和 PUT 相同。Name 的欄位多了 post.index、post.create...等的名稱,這個是 route 的名稱。在 laravel 框架中,你可以像我們範例中指定 連結網址route 名稱 ,最後都會由同一個 Action 也就是 Controller 去執行。

你也可以指定 resource 只產生某幾個 action:
Route::resource('post', 'HomeController', ['only' => ['create','store','destroy']]);

指定 Route Name

之前建立的 route 都沒有指定 route 名稱,所以就只能使用 URI 來請求。這裡示範 Route Name 怎麼寫:
Route::get('post', array('uses' => 'HomeController@index', 'as' => 'post.home'));
原本第二個參數直接指定 Controller@method,把它改為使用陣列,並且使用兩個關鍵字當 key:
  • 'uses' 表示要使用哪個 Controller 的 method
  • 'as' 表示這個 route 的名稱(Name)

如果把這行寫在 Route::resource 這行之後,由 resource 產生的相同 URI 的 route 就會被後面這個 route 取代(表示不會有重覆的route出現),所以自動產生的 route Name 就會是 post.home 而不是 post.index,你可以在終端機下指令觀看 route 表的變化。

要怎麼用 route,簡單舉例。在 app/views/home.blade.php 中,原本的
{{ link_to('post/'.$post->id, $post->title) }}
如果使用 route 的方式,要改為:
{{ link_to_route('post.show', $post->title, ['id'=>$post->id]) }}
備註:查了一下文件,link_to 及 link_to_route 是 3.x 的寫法,在 4.x 之後已經改了寫法,改成 HTML::linkRoute。要查看 4.x 的 API 在這裡,可以直接搜尋'link',或在左邊清單中,找到 Html -> HtmlBuilder 就可以看到全部可以使用的方法。
link_to 改為 HTML::link
link_to_route 改為 HTML::linkRoute

參數(Parameters)

選擇性參數

之前用過的
Route::get('post/{id}', 'HomeController@show');
{id} 就是參數。如果這個參數是選擇性的:
Route::get('post/{id?}', 'HomeController@show');
後面加個問號,當網址是 http://localhost/blog/public/posthttp://localhost/blog/public/post/1 都會由這個 route 控制。因為我們的例子中,已經有 "沒有$id" 的 route 了,所以基本上,這個例子沒作用。

硬舉例的話,先將
Route::get('post', 'HomeController@show');
這行註解掉,就不能作用了。現在連到這個網址 http://localhost/blog/public/post
就會出錯。把 {id} 加上問號 {id?}。接著修改 HomeController 的 show() 為:
public function show($id=null)
{
    if (is_null($id)) {
        return $this->index();
    }

    //下略...
這樣當 $id 為 null 時,就會轉給 index() 去處理。這裡只是舉例,請在必要的時候才這麼做。

參數的正規表示式

Route::get('post/{id}', 'HomeController@show')->where('id', '[0-9]+');
加上 where 去做參數的正規表示式限定。但其實只要 id 不是數字,都會發生錯誤,在於錯誤會不同。

非數字的 id 在加了 pattern 的 URI 中,不會被送入 Controller,而是出現找不到對應的網址錯誤。在加 pattern 之前,非數字的 id 仍會送進 Controller,但在 Model 查詢資料庫時,會因為資料型態不符合(id必須為數值)出現錯誤。

你也可以把模式寫成全域的
Route::pattern('id', '[0-9]+');

記得要寫在最上面,會影響之後所有參數為 id 的 route。

過濾器(filter)

Route 還可以設定過濾器,在執行某個網址之前,先做一些檢查。這些過濾器另外寫在 app/filters.php。之後我們會用到 auth 這個內建的過濾器來做登入的驗證。

Model 綁定(Model Binding)

Route 提供 Model 及資料表的綁定。
Route::model('pp', 'Post');
Route::get('p/{pp}', function(Post $post)
{
    return $post->title;
});
我們把 pp 和 Post 綁定,這時候只要使用參數 {pp} 就會得到一個 Post 物件。也就是 http://localhost/blog/public/p/1 中的 1 會送入 {pp} 所綁定的 Post 物件,並以 id 查詢後,傳回給 $post 變數,然後就可以 $post->title 去取得標題。
本文網址:http://blog.tonycube.com/2015/01/laravel-11-route.html
Tony Blog 撰寫,轉載時請註明出處及文章連結,謝謝 😀

我要留言

留言小提醒:
1.回覆時間通常在晚上,如果太忙可能要等幾天。
2.請先瀏覽一下其他人的留言,也許有人問過同樣的問題。
3.程式碼請先將它編碼後再貼上。(線上編碼:http://bit.ly/1DL6yog)
4.文字請加上標點符號及斷行,難以閱讀者恕難回覆。
5.感謝您的留言,您的問題也可能幫助到其他有相同問題的人。