HTTP 控制器
簡介
除了在單一的 routes.php
檔案中定義所有的請求處理邏輯,你可能希望使用控制器類別來組織此行為。控制器可將相關的 HTTP 請求處理邏輯組成一個類別。控制器一般存放在 app/Http/Controllers
目錄下。
基礎控制器
這是一個基礎控制器類別的範例。所有 Laravel 控制器都應繼承基礎控制器類別,它包含在 Laravel 的預設安裝中:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 顯示給定使用者的個人資料。
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
我們可以經由路由指定控制器行為,就像這樣:
Route::get('user/{id}', 'UserController@showProfile');
現在,當請求和此特定的路由 URI 相匹配時,UserController
類別的 showProfile
方法就會被執行。當然,路由的參數也會被傳遞至該方法。
控制器和命名空間
有一點非常重要,那就是我們在定義控制器路由時,不需要指定完整的控制器命名空間。我們只需要定義「根」命名空間 App\Http\Controllers
之後的部分類別名稱。預設情況下 RouteServiceProvider
會把 routes.php
檔案載入到包含根控制器命名空間的路由群組中。
若你選擇在 App\Http\Controllers
目錄內層,使用 PHP 命名空間巢狀或組織控制器,只要使用相對於 App\Http\Controllers
根命名空間的特定類別名稱即可。因此,若你的控制器類別全名為 App\Http\Controllers\Photos\AdminController
,你可以像這樣註冊一個路由:
Route::get('foo', 'Photos\AdminController@method');
命名控制器路由
就像閉包路由,你可以指定控制器路由的名稱:
Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);
你也可以使用 route
輔助方法,產生命名控制器路由的 URL:
$url = route('name');
控制器中介層
可將中介層指派給控制器路由,例如:
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController@showProfile'
]);
不過,在控制器建構子中指定中介層會更為方便。在控制器建構子中使用 middleware
方法,你可以很容易地將中介層指定給控制器。你甚至可以對中介層作出限制,僅將它提供給控制器類別中的某些方法。
class UserController extends Controller
{
/**
* 新增一個 UserController 實例。
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => [
'fooAction',
'barAction',
]]);
$this->middleware('subscribed', ['except' => [
'fooAction',
'barAction',
]]);
}
}
RESTful 資源控制器
資源控制器讓你可以無痛地建立與資源有關的 RESTful 控制器。例如,你可能想要建立一個控制器,用來處理對你應用程式儲存「相片」發送的 HTTP 請求。使用 make:controller
Artisan 指令,我們可以快速地建立像這樣的控制器:
php artisan make:controller PhotoController --resource
此 Artisan 指令會產生 app/Http/Controllers/PhotoController.php
控制器檔案。此控制器會包含用來操作可取得的各種資源的方法。
接下來,你可以在控制器中註冊資源化路由:
Route::resource('photo', 'PhotoController');
這一條路由宣告會創建多個路由,用來處理各式各樣和相片資源相關的的 RESTful 行為。同樣地,產生的控制器已有各種和這些行為繫結的方法,並包含通知你它們所處理的 URI 及動詞的記錄。
由資源控制器處理的行為
動詞 | 路徑 | 行為 | 路由名稱 |
---|---|---|---|
GET | /photo |
index | photo.index |
GET | /photo/create |
create | photo.create |
POST | /photo |
store | photo.store |
GET | /photo/{photo} |
show | photo.show |
GET | /photo/{photo}/edit |
edit | photo.edit |
PUT/PATCH | /photo/{photo} |
update | photo.update |
DELETE | /photo/{photo} |
destroy | photo.destroy |
部分資源路由
宣告資源路由時,你可以指定讓此路由僅處理一部分的行為:
Route::resource('photo', 'PhotoController', ['only' => [
'index', 'show'
]]);
Route::resource('photo', 'PhotoController', ['except' => [
'create', 'store', 'update', 'destroy'
]]);
命名資源路由
所有的資源控制器行為預設都有一路由名稱;不過你可以在選項中傳遞一個 names
陣列來覆寫這些名稱:
Route::resource('photo', 'PhotoController', ['names' => [
'create' => 'photo.build'
]]);
附加資源控制器
若你必須在資源控制器中預設的資源路由之外,加入額外的路由,你應該在呼叫 Route::resource
之前定義這些路由。否則,由 resource
方法定義的路由可能會意外地覆蓋你附加的路由:
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
依賴注入與控制器
建構子注入
Laravel 服務容器用於解析所有的 Laravel 控制器。因此,在建構子中,你可以對控制器可能需要的任何依賴使用型別提示。依賴會自動被解析並注入控制器實例之中。
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller
{
/**
* 使用者儲存庫實例。
*/
protected $users;
/**
* 建立新的控制器實例。
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
當然,你也可以對任何的 Laravel contract 使用型別提示。若容器能夠解析它,你就可以使用型別提示。
方法注入
除了建構子注入之外,你也可以對控制器行為方法的依賴使用型別提示。例如,讓我們對 Illuminate\Http\Request
實例的其中一個方法使用型別提示:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 儲存一個新的使用者。
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
若你的控制器方法也預期從路由參數獲得輸入值,只要在你其它的依賴之後列出路由參數即可。例如,如果你的路由被定義成這個樣子:
Route::put('user/{id}', 'UserController@update');
你依然可以做 Illuminate\Http\Request
型別提示並透過定義你的控制器方法類似下面範例,來存取你的路由參數 id
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class UserController extends Controller
{
/**
* 更新指定的使用者。
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
路由快取
注意:路由快取並不會作用在基於閉包的路由。要使用路由快取,你必須將所有閉包路由轉換為控制器類別。
若你的應用程式完全透過控制器使用路由,你應該考慮採用 Laravel 的路由快取。使用路由快取可以大幅降低註冊你應用程式全部的路由所需的時間。在某些情況下,你的路由註冊甚至可以快上一百倍!要產生路由快取,只要執行 route:cache
此 Artisan 指令:
php artisan route:cache
這就是全部了!現在你的快取路由檔案將被用來代替 app/Http/routes.php
此一檔案。請記得,若你新增了任何新的路由,就必須產生新的路由快取。因此你應該只在專案部署時才執行 route:cache
指令。
要移除快取路由檔案而不產生新的快取,請使用 route:clear
指令:
php artisan route:clear