# laravel5.4 | 控制器
默认目录 app/Http/Controllers
## 基本控制器
所有的 Laravel 控制器应该继承自 Laravel 自带的控制器基类 Controller,控制器基类提供了一些很方便的方法如 middleware ,用于添加中间件到控制器动作
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 为指定用户显示详情
*
* @param int $id
* @return Response
*/
public function show($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
Route::get('user/{id}', 'UserController@show');
#### 单动作控制器
想要定义一个只处理一个动作的控制器,可以在这个控制器中定义 __invoke
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return Response
*/
public function __invoke($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
当你为这个单动作控制器注册路由的时候,不需要指定方法:
Route::get('user/{id}', 'ShowProfile');
## 控制器中间件
Route::get('profile', 'UserController@show')->middleware('auth');
或
class UserController extends Controller
{
/**
* 实例化一个新的 UserController 实例
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}
在控制器中还可以使用闭包注册中间件,这为我们定义只在某个控制器使用的中间件提供了方便,无需定义完整的中间件类:
$this->middleware(function ($request, $next) {
// ...
return $next($request);
});
注:你还可以将中间件分配给多个控制器动作,不过,这意味着你的控制器会变得越来越臃肿,这种情况下,需要考虑将控制器分割成多个更小的控制器。
## 资源控制器
php artisan make:controller PhotoController --resource
使用路由模型绑定并且想要在资源控制器的方法中对模型实例进行类型提示
php artisan make:controller PhotoController --resource --model=Photo
Route::resource('photos', 'PhotoController');
方法 路径 动作 路由名称
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy
#### 伪造表单方法
表单不能发起PUT、PATCH和DELETE请求,需要添加一个隐藏的 _method 字段来伪造 HTTP 请求方式
{{ method_field('PUT') }}
####部分资源路由
Route::resource('photo', 'PhotoController', ['only' =>
['index', 'show']
]);
Route::resource('photo', 'PhotoController', ['except' =>
['create', 'store', 'update', 'destroy']
]);
#### 命名资源路由
默认情况下, Route::resource 将会基于资源名称的单数格式为资源路由创建路由参数,你可以通过在选项数组中传递 parameters 来覆盖这一默认设置。 parameters 应该是资源名称和参数名称的关联数组:
Route::resource('user', 'AdminUserController', ['parameters' => [
'user' => 'admin_user'
]]);
上面的示例代码会为资源的 show 路由生成如下 URL:
/user/{admin_user}
#### 补充资源控制器
如果有必要在默认资源路由之外添加额外的路由到资源控制器,应该在调用 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
{
/**
* The user repository instance.
*/
protected $users;
/**
* 创建新的控制器实例
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
#### 方法注入
还可以在控制器的动作方法中进行依赖的类型提示
如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');
//
}
}
## 路由缓存
如果你的应用完全基于控制器路由,可以使用 Laravel 的路由缓存,使用路由缓存将会极大减少注册所有应用路由所花费的时间开销,在某些案例中,路由注册速度甚至能提高100倍!想要生成路由缓存,只需执行 Artisan 命令 route:cache:
php artisan route:cache
运行完成后,每次请求都会从缓存中读取路由,记住,如果你添加新的路由需要重新生成路由缓存。因此,只有在项目部署阶段才需要运行 route:cache 命令。
想要移除缓存路由文件,使用 route:clear 命令即可:
php artisan route:clear