• 【PHP框架 | Laravel8 系列6】 - 控制器


    前言:之前在学习并使用 Laravel 框架过程中,全是碎片化掌握,现在重新学习并记录一次学习的过程。

    本文内容对应 Laravel8.* 版本。


    直达入口:


    怎么理解 MVC ,请看 MVC与三层架构理解

    前边的系统,所有的请求都转发到路由闭包中处理了,那实际项目中,不能啥也往路由闭包中写吧。


    这时就可以使用 控制器类了。控制器类存放在 app/Http/Controllers 目录。

    一、基础控制器

    1.1 artisan 命令生成控制器

    Artisan 命令生成的控制器,默认保存在 app/Http/Controllers 目录。

    # 控制台命令生成控制器
    php artisan make:controller UserController
    
    • 1
    • 2

    默认继承 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)]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    1.2 单行为控制器

    什么是单行为控制器?就是只处理单个行为的控制器。

    使用 Artisan 命令时追加 --invokable 选项,即可创建单行为控制器。

    # 控制台命令生成控制器
    php artisan make:controller AboutController --invokable
    
    • 1
    • 2

    在控制器中只有 __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)]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    定义单个行为控制器的路由时不需要指定方法就会自动调用 __invoke 方法。

    use App\Http\Controllers\AboutController;
    
    Route::get('user/{id}', AboutController::class);
    
    • 1
    • 2
    • 3

    二、 控制器中间件

    2.1 分配给控制器的路由中间件

    Route::get('profile', [UserController::class, 'show'])->middleware('auth');
    
    • 1

    2.2 构造函数中间件

    将中间件调用放到控制器的构造函数当中。

    class UserController extends Controller
    {
        /**
         * 实例化一个新的控制器实例
         *
         * @return void
         */
        public function __construct()
        {
            $this->middleware('auth');
    
            $this->middleware('log')->only('index');
    
            $this->middleware('subscribed')->except('store');
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    同时,控制器还允许使用中间件闭包。

    $this->middleware(function ($request, $next) {
        // ...
    
        return $next($request);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、资源控制器

    啥是资源路由:Laravel 的资源路由可通过单行代码将典型的「CURD增删改查」路由分配给控制器。


    啥是资源控制器:通过 artisan 命令生成资源控制器,控制器中包括每个可用资源的操作方法。接着往下看,你就知道了。

    3.1 生成资源控制器

    # 控制台 artisan 命令
    php artisan make:controller PhotoController --resource
    
    # 快速生成 api 控制器
    php artisan make:controller API/PhotoController --api
    
    • 1
    • 2
    • 3
    • 4
    • 5

    生成后,去 app/Http/Controllers 目录找到该控制器,查看控制器内的操作方法。


    3.2 生成资源控制器路由

    使用 resource 注册资源控制器路由

    # 生成单个资源控制器路由
    Route::resource('photos', PhotoController::class);
    
    # 生成多个资源控制器路由
    Route::resources([
        'photos' => PhotoController::class,
        'videos' => VideoController::class
    ]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.3 生成 API 资源控制器路由

    使用 api 路由时,通常会屏蔽显示模板的路由(如 create 和 edit),使用 apiResource 会自动屏蔽。

    # 生成 API 资源路由
    Route::apiResource('photos', PhotoController::class);
    
    # 生成多个 API 资源路由
    Route::apiResource([
        'photos' => PhotoController::class,
        'videos' => VideoController::class
    ]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.4 资源控制器操作处理表

    结合刚生成的控制器类的文件内容,对应查看,就明白啥意思了

    VerbURIActionRoute Name
    GET/photosindexphotos.index
    GET/photos/createcreatephotos.create
    POST/photosstorephotos.store
    GET/photos/{photo}showphotos.show
    GET/photos/{photo}/editeditphotos.edit
    PUT/PATCH/photos/{photo}updatephotos.update
    DELETE/photos/{photo}destroyphotos.destroy

    3.5 指定资源模型

    如果你使用了路由模型绑定,并且想在资源控制器中使用类型提示,那么在生成控制器时,指定模型即可。

    php artisan make:controller VideoController --resource --model=Video
    
    • 1

    指定模型绑定后,执行生成命令,如果模型类不存在,则会提示是是否创建,输入 yes 即可创建。


    默认的默认类存在在 app/Http/Models/ 目录中。


    3.6 部分资源路由

    资源路由,默认处理资源控制器中的所有行为,通过 only 方法可以处理部分行为。

    # 只处理以下方法
    Route::resource('photos', PhotoController::class)->only([
        'index', 'show'
    ]);
    
    # 只处理除以下方法的所有方法
    Route::resource('photos', PhotoController::class)->except([
        'create', 'store', 'update'
    ]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.7 嵌套资源

    有时可能需要一个嵌套的资源型路由。比如,照片资源可能添加了多个评论,那么在路由中就可以使用 「点 .」符号来声明资源型路由。

    Route::resource('photos.comments', PhotoCommentController::class);
    
    • 1

    该路由会注册一个嵌套资源,访问 URI 是:

    /photos/{photo}/comments/{comment}
    
    • 1

    3.8 命名资源路由

    默认情况下,所有资源控制器会生成默认的路由名称,如 create、update 等,但你可以链式调用 names 方法,传入名称数组来替换这些默认的路由名称。

    Route::resource('photos', PhotoController::class)->names([
        'create' => 'photos.build'
    ]);
    
    • 1
    • 2
    • 3

    3.9 命令资源路由参数

    Laravel 默认情况下,会按资源名的「单数」形式创建资源路由的参数。但你可以链式调用 parameters 方法,传入参数名称数组,覆盖默认的参数资源。

    # 以下路由会生成 /users/{admin_user} 的URI
    Route::resource('users', AdminUserController::class)->parameters([
        'users' => 'admin_user'
    ]);
    
    • 1
    • 2
    • 3
    • 4

    四、依赖流入 & 控制器

    4.1 构造函数注入

    构造函数注入就是可以在控制器的构造函数中使用类型提示,来传入需要的依赖项。

    
    
    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4.2 方法注入

    方法注入类似于构造函数注入。

    
    
    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;
    
            //
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    五、路由缓存

    如果项目仅使用了基于路由的控制器,你应该利用 Laravel 的路由缓存。

    # 生成路由缓存
    php artisan route:cache
    
    # 清除路由缓存
    php artisan route:clear
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    8 个 Promise 高级用法
    DG_11g部署
    数据结构系列-堆排序
    swoole 是什么?
    爬虫学习 | 01 Web Scraper的使用
    【POJ No. 1330】 最近公共祖先 Nearest Common Ancestors
    Android应用内组件通讯之EventBus的使用(一)
    云安全-对象存储安全(配置错误,域名接管,AK泄露)
    wsl2 执行exe文件提示 无法执行二进制文件:可执行文件格式错误
    腾讯mini项目-【指标监控服务重构】2023-07-27
  • 原文地址:https://blog.csdn.net/qq_35453862/article/details/127655138