控制器
基本控制器
与其在单个 routes.php
文件中定义所有路由级逻辑,不如使用控制器类来组织这些行为。控制器可以将相关的路由逻辑分组到一个类中,并利用更高级的框架特性,例如自动 依赖注入。
控制器通常存储在 app/controllers
目录中,并且该目录默认在 composer.json
文件的 classmap
选项中注册。然而,控制器实际上可以位于任何目录或子目录中。路由声明不依赖于控制器类文件在磁盘上的位置。因此,只要 Composer 知道如何自动加载控制器类,它可以放置在您希望的任何地方。
以下是一个基本控制器类的示例:
class UserController extends BaseController {
/**
* 显示给定用户的个人资料。
*/
public function showProfile($id)
{
$user = User::find($id);
return View::make('user.profile', array('user' => $user));
}
}
所有控制器都应扩展 BaseController
类。BaseController
也存储在 app/controllers
目录中,可以用作放置共享控制器逻辑的地方。BaseController
扩展了框架的 Controller
类。现在,我们可以像这样路由到这个控制器动作:
Route::get('user/{id}', 'UserController@showProfile');
如果您选择使用 PHP 命名空间来嵌套或组织您的控制器,只需在定义路由时使用完全限定的类名:
Route::get('foo', 'Namespace\FooController@method');
由于我们使用 Composer 来自动加载 PHP 类,控制器可以位于文件系统的任何位置,只要 composer 知道如何加载它们。控制器目录不强制执行应用程序的任何文件夹结构。路由到控制器完全与文件系统解耦。
您还可以在控制器路由上指定名称:
Route::get('foo', array('uses' => 'FooController@method', 'as' => 'name'));
要生成指向控制器动作的 URL,您可以使用 URL::action
方法或 action
辅助方法:
$url = URL::action('FooController@method');
$url = action('FooController@method');
您可以使用 currentRouteAction
方法访问正在运行的控制器动作的名称:
$action = Route::currentRouteAction();
控制器过滤器
过滤器 可以在控制器路由上指定,类似于“常规”路由:
Route::get('profile', array('before' => 'auth',
'uses' => 'UserController@showProfile'));
但是,您也可以从控制器内部指定过滤器:
class UserController extends BaseController {
/**
* 实例化一个新的 UserController 实例。
*/
public function __construct()
{
$this->beforeFilter('auth', array('except' => 'getLogin'));
$this->beforeFilter('csrf', array('on' => 'post'));
$this->afterFilter('log', array('only' =>
array('fooAction', 'barAction')));
}
}
您还可以使用闭包在线指定控制器过滤器:
class UserController extends BaseController {
/**
* 实例化一个新的 UserController 实例。
*/
public function __construct()
{
$this->beforeFilter(function()
{
//
});
}
}
如果您希望在控制器上使用另一个方法作为过滤器,可以使用 @
语法来定义过滤器:
class UserController extends BaseController {
/**
* 实例化一个新的 UserController 实例。
*/
public function __construct()
{
$this->beforeFilter('@filterRequests');
}
/**
* 过滤传入的请求。
*/
public function filterRequests($route, $request)
{
//
}
}
隐式控制器
Laravel 允许您轻松定义一个路由来处理控制器中的每个动作。首先,使用 Route::controller
方法定义路由:
Route::controller('users', 'UserController');
controller
方法接受两个参数。第一个是控制器处理的基本 URI,第二个是控制器的类名。接下来,只需向控制器添加方法,前缀为它们响应的 HTTP 动词:
class UserController extends BaseController {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
public function anyLogin()
{
//
}
}
index
方法将响应控制器处理的根 URI,在这种情况下是 users
。
如果您的控制器动作包含多个单词,您可以在 URI 中使用“破折号”语法访问该动作。例如,以下控制器动作在我们的 UserController
中将响应 users/admin-profile
URI:
public function getAdminProfile() {}
RESTful资源控制器
资源控制器使围绕资源构建 RESTful 控制器变得更加容易。例如,您可能希望创建一个控制器来管理应用程序存储的“照片”。通过 Artisan CLI 的 controller:make
命令和 Route::resource
方法,我们可以快速创建这样的控制器。
要通过命令行创建控制器,请执行以下命令:
php artisan controller:make PhotoController
现在我们可以将资源路由注册到控制器:
Route::resource('photo', 'PhotoController');
这条单一的路由声明创建了多个路由,以处理对照片资源的各种 RESTful 操作。同样,生成的控制器将已经为每个这些操作提供了存根方法,并附有说明它们处理的 URI 和动词的注释。
资源控制器处理的操作
动词 | 路径 | 操作 | 路由名称 |
---|---|---|---|
GET | /resource | index | resource.index |
GET | /resource/create | create | resource.create |
POST | /resource | store | resource.store |
GET | /resource/ | show | resource.show |
GET | /resource/{resource}/edit | edit | resource.edit |
PUT/PATCH | /resource/ | update | resource.update |
DELETE | /resource/ | destroy | resource.destroy |
有时您可能只需要处理资源操作的子集:
php artisan controller:make PhotoController --only=index,show
php artisan controller:make PhotoController --except=index
您还可以在路由上指定要处理的操作子集:
Route::resource('photo', 'PhotoController',
array('only' => array('index', 'show')));
Route::resource('photo', 'PhotoController',
array('except' => array('create', 'store', 'update', 'destroy')));
默认情况下,所有资源控制器操作都有一个路由名称;但是,您可以通过传递一个 names
数组来覆盖这些名称:
Route::resource('photo', 'PhotoController',
array('names' => array('create' => 'photo.build')));
处理嵌套资源控制器
要“嵌套”资源控制器,请在路由声明中使用“点”符号:
Route::resource('photos.comments', 'PhotoCommentController');
此路由将注册一个“嵌套”资源,可以通过以下 URL 访问:photos/{photoResource}/comments/{commentResource}
。
class PhotoCommentController extends BaseController {
public function show($photoId, $commentId)
{
//
}
}
向资源控制器添加额外路由
如果您需要向资源控制器添加额外的路由,超出默认资源路由,您应该在调用 Route::resource
之前定义这些路由:
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
处理缺失的方法
使用 Route::controller
时,可以定义一个捕获所有方法,该方法将在给定控制器上找不到其他匹配方法时被调用。该方法应命名为 missingMethod
,并接收请求的参数和方法参数数组:
定义捕获所有方法
public function missingMethod($parameters = array())
{
//
}
如果您使用资源控制器,您应该在控制器上定义一个 __call
魔术方法来处理任何缺失的方法。