一.简介
将所有的请求处理逻辑都放在单个routes.php 中肯定是不合理的,你也许还希望使用控制器类组织管理这些行为。控制器可以将相关的 HTTP 请求封装到一个类中进行处理。通常控制器存放在app/Http/Controllers 目录中。
二.基本控制器
1.简单示例
下面是一个基本控制器类的例子。所有的 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)]);
}
}
路由定义
Route::get('user/{id}', 'UserController@showProfile');
现在,如果一个请求匹配上面的路由 URI, UserController 的showProfile 方法就会被执行。当然,路由参数
也会被传递给这个方法。
2.控制器&命名空间
你应该注意到我们在定义控制器路由的时候没有指定完整的控制器命名空间,而只是定义了App\Http\Controllers 之后的部分。默认情况下, RouteServiceProvider 将会在一个路由分组中载入routes.php 文件,并且该路由分组指定定了分组中路由控制器所在的命名空间。
如果你在App\Http\Controllers 目录下选择使用 PHP 命名空间嵌套或组织控制器,只需要使用相对于App\Http\Controllers 命名空间的指定类名即可。因此,如果你的完整控制器类是App\Http\Controllers\Photos\AdminController ,你可以像这样注册路由:
Route::get('foo', 'Photos\AdminController@method');
3.命名控制器路由(如果get第二个参数为字符串,则默认key为uses)
Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);
使用action生成对应URL
$url = action('FooController@method');
还可以使用帮助函数route 来为已命名的控制器路由生成对应的 URL
$url = route('name');
4.控制器中使用中间件
$this->middleware('auth');
三.RESTful 资源控制器
1.资源控制器
使用 Artisan 命令make:controller ,我们可以快速创建一个带有RESTful风格的控制器:
php artisan make:controller PhotoController
该 Artisan 命令将会生成一个控制器文件app/Http/Controllers/PhotoController.php ,这个控制器包含了每一个资源操作对应的方法。 接下来,可以为该控制器注册一个资源路由:
Route::resource('photo', 'PhotoController');
这个路由声明包含了处理图片资源 RESTful 动作的多个路由,相应地,Artisan 生成的控制器也已经为这些动作设置了对应的处理方法。
2.定义部分资源路由
#仅仅index,show方法可用
Route::resource('photo', 'PhotoController',
['only' => ['index', 'show']]);
#除except里面的方法不可用,其余可用
Route::resource('photo', 'PhotoController',
['except' => ['create', 'store', 'update', 'destroy']]);
3.命名资源路由
默认情况下,所有资源控制器动作都有一个路由名称,然而,我们可以通过传入 names 数组来覆盖这些默认的名字:
Route::resource('photo', 'PhotoController',['names' => ['create' => 'photo.build']]);
使用
route('photo.build');
即可取出对应url,如http://localhost:9000/photo/create
route/url/action的区别,
Route::resource('photo', 'PhotoController');
route('photo.index'); //如果路由有命名,可以取他的名字,如as定义的名字
url('photo');
action('PhotoController@index');
这三者取出的地址都是http://localhost:9000/photo,但每个函数的参数形式不同;
4.嵌套资源
有时候我们需要定义路由到“嵌套”资源。例如,一个图片资源可能拥有多条“评论”,要“嵌套”资源控制器,在路由声明中使用“.”号即可:
Route::resource('photos.comments', 'PhotoCommentController');
控制器中:
class PhotoCommentController extends Controller
{
/**
* 显示指定照片评论
*
* @param int $photoId
* @param int $commentId
* @return Response
* @translator http://laravelacademy.org
*/
public function show($photoId, $commentId)
{
//
}
}
5.补充资源控制器
如果有必要在默认资源路由之外添加额外的路由到资源控制器,应该在调用Route::resource 之前定义这些路由;否则,通过resource 方法定义的路由可能无意中优先于补充的额外路由:
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
6.隐式控制器
(1).Laravel 允许你只定义一个路由即可访问控制器类中的所有动作,首先,使用Route::controller 方法定义一个路由,该controller 方法接收两个参数,第一个参数是控制器处理的 baseURI,第二个参数是控制器的类名:
Route::controller('users', 'UserController');
接下来,添加方法到控制器,方法名应该以 HTTP 请求方法开头:
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
/**
* 响应 GET /users 请求
*/
public function getIndex()
{
//
}
/**
* 响应 GET /users/show/1 请求
*/
public function getShow($id)
{
//
}
/**
* 响应 GET /users/admin-profile 请求
*/
public function getAdminProfile()
{
//
}
/**
* 响应 POST /users/profile 请求
*/
public function postProfile()
{
//
}
}
在上例中可以看到, getIndex 方法将会在访问控制器处理的默认 URI: /users 时被调用。
(2).分配路由名称
如果你想要命名该控制器中的一些路由,可以将一个名称数组作为第三个参数传递到该controller 方法:
Route::controller('users', 'UserController', [
'getShow' => 'user.show',
]);
使用route取出对应url
route('guo.show');
四.依赖注入 & 控制器
1.构造函数注入
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 契约,如果容器可以解析,就可以进行类型提示。
2.方法注入
<?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 :
public function update(Request $request, $id)
{
//
}
四.路由缓存
1.生成路由缓存
php artisan route:cache
缓存路由文件(在bootstrap/cache/下)现在取代app/Http/routes.php 文件被使用.
因此,只有在项目运行阶段你才会运行route:cache 命令
2.清除路由缓存
php artisan route:clear