[TOC]
### **1、簡介**
將所有的請求處理邏輯都放在單個?`routes.php`?中顯然是不合理的,你也許還希望使用[控制器](http://laravelacademy.org/tags/%e6%8e%a7%e5%88%b6%e5%99%a8 "View all posts in 控制器")類組織管理這些行為。控制器可以將相關的 HTTP 請求封裝到一個類中進行處理。通常控制器存放在?`app/Http/Controllers`?目錄中。
### **2、基本控制器**
下面是一個基本控制器類的例子。所有的?[Laravel](http://laravelacademy.org/tags/laravel "View all posts in Laravel")?控制器應該繼承自 Laravel 自帶的控制器基類?`Controller`:
~~~
<?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)]);
}
}
~~~
我們可以像這樣定義指向該控制器動作的[路由](http://laravelacademy.org/tags/%e8%b7%af%e7%94%b1 "View all posts in 路由"):
~~~
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');
~~~
### **3、控制器[中間件](http://laravelacademy.org/tags/%e4%b8%ad%e9%97%b4%e4%bb%b6 "View all posts in 中間件")**
中間件可以像這樣分配給控制器路由:
~~~
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']]);
}
}
~~~
### **4、[RESTful](http://laravelacademy.org/tags/restful "View all posts in RESTful")?資源控制器**
Laravel 的資源控制器使得構建圍繞資源的 RESTful 控制器變得毫無痛苦,例如,你可能想要在應用中創建一個控制器,用于處理關于圖片存儲的 HTTP 請求,使用 Artisan 命令?`make:controller`,我們可以快速創建這樣的控制器:
~~~
php artisan make:controller PhotoController --resource
~~~
該 Artisan 命令將會生成一個控制器文件?`app/Http/Controllers/PhotoController.php`,這個控制器包含了每一個資源操作對應的方法。
接下來,可以為該控制器注冊一個資源路由:
~~~
Route::resource('photo', 'PhotoController');
~~~
這個路由聲明包含了處理圖片資源 RESTful 動作的多個路由,相應地,Artisan 生成的控制器也已經為這些動作設置了對應的處理方法。
#### **資源控制器處理的動作**
| 方法 | 路徑 | 動作 | 路由名稱 |
| --- | --- | --- | --- |
| 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');
~~~
### **5、[依賴注入](http://laravelacademy.org/tags/%e4%be%9d%e8%b5%96%e6%b3%a8%e5%85%a5 "View all posts in 依賴注入")?& 控制器**
#### **構造函數注入**
Laravel 使用服務容器解析所有的 Laravel 控制器,因此,可以在控制器的構造函數中類型聲明任何依賴,這些依賴會被自動解析并注入到控制器實例中:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use App\Repositories\UserRepository;
class UserController extends Controller
{
/**
* The user repository instance.
*/
protected $users;
/**
* 創建新的控制器實例
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
~~~
當然,你還可以類型提示任何 Laravel 契約,如果容器可以解析,就可以進行類型提示。
#### **方法注入**
除了構造函數注入之外,還可以在控制器的動作方法中進行依賴的類型提示,例如,我們可以在某個方法中類型提示 ?`Illuminate\Http\Request`?實例:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
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 int $id
* @return Response
* @translator http://laravelacademy.org
*/
public function update(Request $request, $id)
{
//
}
}
~~~
### **6、路由緩存**
> 注意:路由緩存不會作用于基于閉包的路由。要使用路由緩存,必須將閉包路由轉化為控制器路由。
如果你的應用完全基于控制器路由,可以使用 Laravel 的路由緩存,使用路由緩存將會極大減少注冊所有應用路由所花費的時間開銷,在某些案例中,路由注冊速度甚至能提高100倍!想要生成路由緩存,只需執行 Artisan 命令`route:cache`:
~~~
php artisan route:cache
~~~
就這么簡單!你的緩存路由文件現在取代?`app/Http/routes.php`?文件被使用,記住,如果你添加新的路由需要重新生成路由緩存。因此,只有在項目部署階段才需要運行?`route:cache`?命令。
想要移除緩存路由文件,使用?`route:clear`?命令即可:
~~~
php artisan route:clear
~~~
- 序言
- 發行版本說明
- 升級指南
- 貢獻代碼
- 開始
- 安裝
- 配置
- Laravel Homestead
- 基礎
- HTTP 路由
- HTTP 中間件
- HTTP 控制器
- HTTP 請求
- HTTP 響應
- 視圖
- Blade 模板引擎
- 架構
- 一次請求的生命周期
- 應用目錄結構
- 服務提供者
- 服務容器
- 門面(Facades)
- 數據庫
- 起步
- 查詢構建器
- 遷移
- 填充數據
- Eloquent ORM
- 起步
- 關聯關系
- 集合
- 訪問器&修改器
- 序列化
- 服務
- 用戶認證
- 用戶授權
- Artisan Console
- 訂閱支付實現:Laravel Cashier
- 緩存
- 集合
- 集成前端資源:Laravel Elixir
- 加密
- 錯誤&日志
- 事件
- 文件系統/云存儲
- 哈希
- 輔助函數
- 本地化
- 郵件
- 包開發
- 分頁
- Redis
- 隊列
- Session
- Envoy Task Runner
- 任務調度
- 測試
- 驗證
- 新手入門指南
- 簡單任務管理系統
- 帶用戶功能的任務管理系統