前言:之前在学习并使用 Laravel 框架过程中,全是碎片化掌握,现在重新学习并记录一次学习的过程。
本文内容对应
Laravel8.*
版本。
直达入口:
怎么理解 MVC ,请看 MVC与三层架构理解。
前边的系统,所有的请求都转发到路由闭包中处理了,那实际项目中,不能啥也往路由闭包中写吧。
这时就可以使用 控制器类了。控制器类存放在
app/Http/Controllers
目录。
Artisan
命令生成的控制器,默认保存在app/Http/Controllers
目录。
# 控制台命令生成控制器
php artisan make:controller UserController
默认继承
Laravel
的基础控制器。
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\User;
class UserController extends Controller
{
/**
* 显示指定用户的简介
*
* @param int $id
* @return \Illuminate\View\View
*/
public function show($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
什么是单行为控制器?就是只处理单个行为的控制器。
使用
Artisan
命令时追加--invokable
选项,即可创建单行为控制器。
# 控制台命令生成控制器
php artisan make:controller AboutController --invokable
在控制器中只有
__invoke
方法。
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\User;
class AboutController extends Controller
{
/**
* 显示指定用户的简介
*
* @param int $id
* @return \Illuminate\View\View
*/
public function __invoke($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
定义单个行为控制器的路由时不需要指定方法就会自动调用
__invoke
方法。
use App\Http\Controllers\AboutController;
Route::get('user/{id}', AboutController::class);
Route::get('profile', [UserController::class, 'show'])->middleware('auth');
将中间件调用放到控制器的构造函数当中。
class UserController extends Controller
{
/**
* 实例化一个新的控制器实例
*
* @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);
});
啥是资源路由:Laravel 的资源路由可通过单行代码将典型的「CURD增删改查」路由分配给控制器。
啥是资源控制器:通过artisan
命令生成资源控制器,控制器中包括每个可用资源的操作方法。接着往下看,你就知道了。
# 控制台 artisan 命令
php artisan make:controller PhotoController --resource
# 快速生成 api 控制器
php artisan make:controller API/PhotoController --api
生成后,去
app/Http/Controllers
目录找到该控制器,查看控制器内的操作方法。
使用
resource
注册资源控制器路由
# 生成单个资源控制器路由
Route::resource('photos', PhotoController::class);
# 生成多个资源控制器路由
Route::resources([
'photos' => PhotoController::class,
'videos' => VideoController::class
]);
使用 api 路由时,通常会屏蔽显示模板的路由(如 create 和 edit),使用
apiResource
会自动屏蔽。
# 生成 API 资源路由
Route::apiResource('photos', PhotoController::class);
# 生成多个 API 资源路由
Route::apiResource([
'photos' => PhotoController::class,
'videos' => VideoController::class
]);
结合刚生成的控制器类的文件内容,对应查看,就明白啥意思了
Verb | URI | Action | Route Name |
---|---|---|---|
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 |
如果你使用了路由模型绑定,并且想在资源控制器中使用类型提示,那么在生成控制器时,指定模型即可。
php artisan make:controller VideoController --resource --model=Video
指定模型绑定后,执行生成命令,如果模型类不存在,则会提示是是否创建,输入
yes
即可创建。
默认的默认类存在在
app/Http/Models/
目录中。
资源路由,默认处理资源控制器中的所有行为,通过
only
方法可以处理部分行为。
# 只处理以下方法
Route::resource('photos', PhotoController::class)->only([
'index', 'show'
]);
# 只处理除以下方法的所有方法
Route::resource('photos', PhotoController::class)->except([
'create', 'store', 'update'
]);
有时可能需要一个嵌套的资源型路由。比如,照片资源可能添加了多个评论,那么在路由中就可以使用 「点 .」符号来声明资源型路由。
Route::resource('photos.comments', PhotoCommentController::class);
该路由会注册一个嵌套资源,访问
URI
是:
/photos/{photo}/comments/{comment}
默认情况下,所有资源控制器会生成默认的路由名称,如
create、update
等,但你可以链式调用names
方法,传入名称数组来替换这些默认的路由名称。
Route::resource('photos', PhotoController::class)->names([
'create' => 'photos.build'
]);
Laravel 默认情况下,会按资源名的「单数」形式创建资源路由的参数。但你可以链式调用
parameters
方法,传入参数名称数组,覆盖默认的参数资源。
# 以下路由会生成 /users/{admin_user} 的URI
Route::resource('users', AdminUserController::class)->parameters([
'users' => 'admin_user'
]);
构造函数注入就是可以在控制器的构造函数中使用类型提示,来传入需要的依赖项。
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller
{
/**
* 用户 repository 实例。
*/
protected $users;
/**
* 创建一个新的控制器实例。
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
方法注入类似于构造函数注入。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 保存一个新用户。
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->name;
//
}
}
如果项目仅使用了基于路由的控制器,你应该利用
Laravel
的路由缓存。
# 生成路由缓存
php artisan route:cache
# 清除路由缓存
php artisan route:clear