將所有的請(qǐng)求處理邏輯都放在單個(gè) routes.php
中肯定是不合理的,你也許還希望使用控制器類組織管理這些行為??刂破骺梢詫⑾嚓P(guān)的 HTTP 請(qǐng)求封裝到一個(gè)類中進(jìn)行處理。通常控制器存放在 app/Http/Controllers
目錄中。
下面是一個(gè)基本控制器類的例子。所有的 Laravel 控制器應(yīng)該繼承自 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)]);
}
}
我們可以像這樣定義指向該控制器動(dòng)作的路由:
Route::get('user/{id}', 'UserController@showProfile');
現(xiàn)在,如果一個(gè)請(qǐng)求匹配上面的路由 URI,UserController
的 showProfile
方法就會(huì)被執(zhí)行。當(dāng)然,路由參數(shù)也會(huì)被傳遞給這個(gè)方法。
你應(yīng)該注意到我們?cè)诙x控制器路由的時(shí)候沒有指定完整的控制器命名空間,而只是定義了 App\Http\Controllers
之后的部分。默認(rèn)情況下,RouteServiceProvider
將會(huì)在一個(gè)路由分組中載入 routes.php
文件,并且該路由分組指定定了分組中路由控制器所在的命名空間。
如果你在 App\Http\Controllers
目錄下選擇使用 PHP 命名空間嵌套或組織控制器,只需要使用相對(duì)于 App\Http\Controllers
命名空間的指定類名即可。因此,如果你的完整控制器類是 App\Http\Controllers\Photos\AdminController
,你可以像這樣注冊(cè)路由:
Route::get('foo', 'Photos\AdminController@method');
和閉包路由一樣,可以指定控制器路由的名字:
Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);
設(shè)置好控制器路由后,就可以使用幫助函數(shù) action
很方便地為控制器動(dòng)作生成對(duì)應(yīng)的 URL:
$url = action('FooController@method');
你還可以使用幫助函數(shù) route
來為已命名的控制器路由生成對(duì)應(yīng)的 URL:
$url = route('name');
中間件可以像這樣分配給控制器路由:
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController@showProfile'
]);
但是,將中間件放在控制器構(gòu)造函數(shù)中更方便,在控制器的構(gòu)造函數(shù)中使用 middleware
方法你可以很輕松的分配中間件給該控制器。你甚至可以限定該中間件應(yīng)用到該控制器類的指定方法:
class UserController extends Controller
{
/**
* 實(shí)例化一個(gè)新的 UserController 實(shí)例
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => ['fooAction', 'barAction']]);
$this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
}
}
Laravel 的資源控制器使得構(gòu)建圍繞資源的 RESTful 控制器變得毫無痛苦,例如,你可能想要在應(yīng)用中創(chuàng)建一個(gè)控制器,用于處理關(guān)于圖片存儲(chǔ)的 HTTP 請(qǐng)求,使用 Artisan 命令 make:controller
,我們可以快速創(chuàng)建這樣的控制器:
php artisan make:controller PhotoController
該 Artisan 命令將會(huì)生成一個(gè)控制器文件 app/Http/Controllers/PhotoController.php
,這個(gè)控制器包含了每一個(gè)資源操作對(duì)應(yīng)的方法。
接下來,可以為該控制器注冊(cè)一個(gè)資源路由:
Route::resource('photo', 'PhotoController');
這個(gè)路由聲明包含了處理圖片資源 RESTful 動(dòng)作的多個(gè)路由,相應(yīng)地,Artisan 生成的控制器也已經(jīng)為這些動(dòng)作設(shè)置了對(duì)應(yīng)的處理方法。
http://wiki.jikexueyuan.com/project/laravel-5.1/images/1.png" alt="" />
聲明資源路由時(shí)可以指定該路由處理的動(dòng)作子集:
Route::resource('photo', 'PhotoController',
['only' => ['index', 'show']]);
Route::resource('photo', 'PhotoController',
['except' => ['create', 'store', 'update', 'destroy']]);
默認(rèn)情況下,所有資源控制器動(dòng)作都有一個(gè)路由名稱,然而,我們可以通過傳入 names 數(shù)組來覆蓋這些默認(rèn)的名字:
Route::resource('photo', 'PhotoController',
['names' => ['create' => 'photo.build']]);
有時(shí)候我們需要定義路由到“嵌套”資源。例如,一個(gè)圖片資源可能擁有多條“評(píng)論”,要“嵌套”資源控制器,在路由聲明中使用“.”號(hào)即可:
Route::resource('photos.comments', 'PhotoCommentController');
該路由將注冊(cè)一個(gè)嵌套的資源,使用 URL 訪問方式如下:
photos/{photos}/comments/{comments}
.
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class PhotoCommentController extends Controller
{
/**
* 顯示指定照片評(píng)論
*
* @param int $photoId
* @param int $commentId
* @return Response
* @translator http://laravelacademy.org
*/
public function show($photoId, $commentId)
{
//
}
}
如果有必要在默認(rèn)資源路由之外添加額外的路由到資源控制器,應(yīng)該在調(diào)用 Route::resource
之前定義這些路由;否則,通過 resource
方法定義的路由可能無意中優(yōu)先于補(bǔ)充的額外路由:
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
擴(kuò)展閱讀:實(shí)例教程——?jiǎng)?chuàng)建 RESTFul 風(fēng)格控制器實(shí)現(xiàn)文章增刪改查
Laravel 允許你只定義一個(gè)路由即可訪問控制器類中的所有動(dòng)作,首先,使用 Route::controller
方法定義一個(gè)路由,該 controller
方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是控制器處理的 baseURI,第二個(gè)參數(shù)是控制器的類名:
Route::controller('users', 'UserController');
接下來,添加方法到控制器,方法名應(yīng)該以 HTTP 請(qǐng)求方法開頭:
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
/**
* 響應(yīng) GET /users 請(qǐng)求
*/
public function getIndex()
{
//
}
/**
* 響應(yīng) GET /users/show/1 請(qǐng)求
*/
public function getShow($id)
{
//
}
/**
* 響應(yīng) GET /users/admin-profile 請(qǐng)求
*/
public function getAdminProfile()
{
//
}
/**
* 響應(yīng) POST /users/profile 請(qǐng)求
*/
public function postProfile()
{
//
}
}
在上例中可以看到,getIndex
方法將會(huì)在訪問控制器處理的默認(rèn) URI——users 時(shí)被調(diào)用。
如果你想要命名該控制器中的一些路由,可以將一個(gè)名稱數(shù)組作為第三個(gè)參數(shù)傳遞到該 controller
方法:
Route::controller('users', 'UserController', [
'getShow' => 'user.show',
]);
Laravel 使用服務(wù)容器解析所有的 Laravel 控制器,因此,可以在控制器的構(gòu)造函數(shù)中類型聲明任何依賴,這些依賴會(huì)被自動(dòng)解析并注入到控制器實(shí)例中:
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use App\Repositories\UserRepository;
class UserController extends Controller
{
/**
* The user repository instance.
*/
protected $users;
/**
* 創(chuàng)建新的控制器實(shí)例
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
當(dāng)然,你還可以類型提示任何 Laravel 契約,如果容器可以解析,就可以進(jìn)行類型提示。
除了構(gòu)造函數(shù)注入之外,還可以在控制器的動(dòng)作方法中進(jìn)行依賴的類型提示,例如,我們可以在某個(gè)方法中類型提示 Illuminate\Http\Request
實(shí)例:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class UserController extends Controller
{
/**
* 存儲(chǔ)新用戶
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
如果控制器方法期望輸入路由參數(shù),只需要將路由參數(shù)放到其他依賴之后,例如,如果你的路由定義如下:
Route::put('user/{id}', 'UserController@update');
你需要通過定義控制器方法如下所示來類型提示 Illuminate\Http\Request
并訪問路由參數(shù) 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)
{
//
}
}
如果你的應(yīng)用完全基于路由使用控制器,可以使用 Laravel 的路由緩存,使用路由緩存將會(huì)極大減少注冊(cè)所有應(yīng)用路由所花費(fèi)的時(shí)間開銷,在某些案例中,路由注冊(cè)速度甚至能提高 100 倍!想要生成路由緩存,只需執(zhí)行 Artisan 命令 route:cache
:
php artisan route:cache
就這么簡(jiǎn)單!你的緩存路由文件現(xiàn)在取代 app/Http/routes.php
文件被使用,記住,如果你添加新的路由需要重新生成路由緩存。因此,只有在項(xiàng)目開發(fā)階段你才會(huì)運(yùn)行 route:cache
命令。
想要移除緩存路由文件,使用 route:clear
命令即可:
php artisan route:clear