HTTP 控制器
簡介
控制器允許你將相應(yīng)的路由業(yè)務(wù)邏輯封裝在控制器類中進行有效的管理,這樣你不必將所有的路由邏輯集中到routes.php
文件中姻锁,導致代碼的臃腫與難以維護。
所有的控制器類都被存儲在app/Http/Controllers
目錄中.
基本控制器
一個基本的控制器應(yīng)該繼承自App\Http\Controllers\Controller
控制器類:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller {
public function showProfile($id) {
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
我們可以通過下面的方式把控制器的行為分配到路由:
Route::get('user/{id}', 'UserController@showProfile');
一旦將控制器的行為分配到路由之后,每次客戶端請求該路由凄敢,都會觸發(fā)控制器的行為凉唐。這里即客戶端每次請求user/{id}
路由庸追,showProfile
方法都會被執(zhí)行,路由中的參數(shù)也會被直接傳遞到該方法中.
控制器 & 命名空間
你應(yīng)該知道我們在定義控制器路由時是不需要指定控制器的命名空間的台囱,而只需要指定到類名就可以了淡溯,這是因為在RouteServiceProvider
文件中自動加載的routes.php
文件已經(jīng)被指定了路由組的根命名空間App\Http\Controllers
;
如果你想在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 = route('name');
控制器中間件
中間件可以這樣被分配到控制器路由中:
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController@showProfile'
]);
當然你也可以在控制器類中直接使用middleware
方法來進行中間件的分配,你也可以只允許類中的某些行為受到指定中間件的約束:
class UserController extends Controller {
public function __construct() {
$this->middleware('auth');
$this->middleware('log', ['only' => [
'fooAction',
'barAction'
]]);
$this->middleware('subscribed', ['except' => [
'fooAction',
'barAction'
]]);
}
}
RESTful 資源控制器
資源控制器可以使你快速的構(gòu)建RESTful型的控制器豺总。你可以使用artisan命令來快速的創(chuàng)建:
php artisan make:controller PhotoController --resource
該命令會生成app\Http\Controllers\PhotoController.php
文件车伞,資源控制器中將包含每個可用的資源操作相應(yīng)的方法.
你可以通過下面的方式來進行資源路由的注冊:
Route::resource('photo', 'PhotoController');
這一個簡單的聲明會創(chuàng)造多條路由用來處理RESTful式的請求.相應(yīng)的通過命令生成的資源型控制器也為這些請求設(shè)置了對應(yīng)的處理方法.
資源控制器所處理的行為
請求方式 | 路由地址 | 控制器行為 | 路由命名 |
---|---|---|---|
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'
]]);
命名資源路由
默認的喻喳,所有的資源控制器行為都被進行了相應(yīng)的路由命名另玖,你可以通過names
參數(shù)來進行重命名:
Route::resource('photo', 'PhotoController', ['names' => [
'create' => 'photo.build'
]]);
命名資源路由參數(shù)
默認的,資源路由的路由參數(shù)都被命名為相應(yīng)的資源名稱表伦,你可以用過parameters
參數(shù)來進行重命名:
Route::resource('user', 'AdminUserController', ['parameters' => [
'user' => 'admin_user'
]]);
// /user/{admin_user}
有時候你可能希望資源路由的路由參數(shù)并不需要像默認的資源名稱一樣采取復數(shù)的形式谦去,那么你可以通過傳遞parameters
的選項設(shè)置為singular
:
Route::resource('users.photos', 'PhotoController', [
'parameters' => 'singular'
]);
// /users/{user}/photos/{photo}
另外,你也可以全局設(shè)置你的資源路由參數(shù)為單數(shù)形式或者全局進行資源路由參數(shù)的命名映射:
Route::singularResourceParameters();
Route::resourceParameters([
'user' => 'person',
'photo' => 'image'
])
當你對資源路由參數(shù)進行定制時蹦哼,你應(yīng)該清楚的知道命名的順序優(yōu)先級:
- 參數(shù)被直接的傳遞給
Route::resource
- 通過
Router::resourceParameters
進行全局參數(shù)映射 - 通過
parameters
數(shù)組選項傳遞給Route::resource
或者 通過Route::singularResoureParameters
進行單數(shù)形式參數(shù)設(shè)置 - 默認行為
資源控制器中意外的行為
如果你必須在資源控制器中添加額外的行為去注冊相應(yīng)的路由鳄哭,那么你一定要在使用Route::resource
之前進行注冊,否則該行為很可能會被資源控制器意外的覆蓋掉.
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
依賴注入 & 控制器
構(gòu)造器注入
laravel的服務(wù)容器支持所有的laravel控制器的解析。由于這個原因纲熏,所以你可以在控制器的構(gòu)造函數(shù)中添加你所需要依賴的相應(yīng)類型提示妆丘,這些依賴會被自動的解析并注入進控制器實例.
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller {
protected $users;
public function __construct(UserRepository $users) {
$this->users = $users;
}
}
當然,你也被允許添加一些laravel contract
的類型提示局劲,只要服務(wù)容器能夠正確的解析勺拣,你都可以被允許添加。
方法注入
除了在構(gòu)造函數(shù)中進行依賴注入鱼填,你也可以在控制器的行為方法中進行依賴注入药有,比如,將Illuminate\Http\Reqeust
實例注入到控制器的store方法中:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller {
public function store (Request $request) {
$name = $request->input('name');
}
}
如果你的控制器方法也接收從路由傳遞過來的參數(shù)苹丸,那么他們會在其它依賴解析完畢之后被傳遞愤惰,比如你的路由是這么定義的:
Route::put('user/{id}', 'UserController@update');
那么你可以這么修正你的控制器行為,來進行參數(shù)的接收:
<?php
namespace App\Http\controllers;
use Illuminate\Http\Request;
class UserController extends Controller {
public function update (Request $request, $id) {
//
}
}
緩存路由
注意:緩存路由不支持閉包函數(shù)定義的路由,如果你想使你的路由被緩存赘理,那么你應(yīng)該使用控制器來管理你的路由.
如果你所有的路由都是基于控制器的路由宦言,那么你應(yīng)該使用laravel推薦的緩存路由,你可以簡單的通過artisan命令來緩存所有路由注冊到同一個文件里感憾,它會替代routes.php
文件被解析蜡励,使用這種緩存注冊路由的方式在某些情況下注冊路由的時間將被大大的減少,從而提高了應(yīng)用的響應(yīng)速度阻桅。
但是每次添加新的路由或者刪除路由時凉倚,為了使路由生效,你需要重新生成一次緩存路由:
php artisan route:cache
你可以通過下面的方式去刪除路由緩存:
php artisan route:clear