笔记:make命令定制类文件技巧

写在前面

Laravel 框架的 Artisan 控制台提供了 make 命令可用于创建各种类,例如控制器、作业、模型等。这些强大又方便的类生成功能都是使用 stub 文件而来。在实际开发过程中可能因 代码设计/架构 不同,需要对生成的类文件进行更改。为了不重复的每次都修改相同内容,就可以修改 stub 模板文件,从而提升开发效率。

快速开始

  1. 发布框架自己的 .stub 文件,将最常见的 Stub 模板发布到你的应用程序中,对相应的.stub 文件进行修改就可以影响对应生成的类文件。命令:
    php artisan stub:publish
  2. 自定义 .sub 文件时避免与系统发布的 .stub 文件混淆,这里新建目录 stubs/custom。如:自定义 service.stub
<?php

namespace {{ namespace }};


use Illuminate\Database\Eloquent\Builder;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

class {{ class }}
{

    public function __construct()
    {
    }

    /**
     * 获取 model::query()
     *
     * @return Builder
     */
    public static function query(): Builder
    {
        //return Demo::query();
    }

    /**
     * 新增 check
     *
     * @param $params
     * @return bool|array
     */
    public function addCheck($params): bool|array
    {
        $name = $params['name'];
        $exist = self::query()->where('name', $name)->first();
        if ($exist) {
            return ['ok' => false, 'msg' => '请修改:名称已存在'];
        }

        return true;
    }

    /**
     * 新增
     *
     * @param array $params
     * @return array
     */
    public function add(array $params): array
    {
        $data = [
            'name' => $params['name'],
            'remark' => $params['remark'] ?? '',
        ];
        $rs = self::query()->create($data);
        if (!$rs) {
            return ['ok' => false, 'msg' => '失败'];
        }

        return ['ok' => true, 'data' => $rs->toArray()];
    }

    /**
     * 编辑 check
     *
     * @param array $params
     * @return bool|array
     */
    public function editCheck(array $params): bool|array
    {
        $id = $params['id'];
        $exist = self::query()->where('id', $id)->first();
        if (!$exist) {
            return ['ok' => false, 'msg' => 'id不存在'];
        }
        //自定义check逻辑


        return true;
    }

    /**
     * 编辑
     *
     * @param array $params
     * @return array
     */
    public function edit(array $params): array
    {
        $id = $params['id'];
        $data = [
            'name' => $params['name'],
            'remark' => $params['remark'] ?? '',
        ];
        $rs = self::query()->where('id', $id)->update($data);
        if (!$rs) {
            return ['ok' => false, 'msg' => '失败'];
        }

        return ['ok' => true, 'data' => ['rs' => $rs]];
    }

    /**
     * 删除 check
     *
     * @param int $id
     * @return bool|array
     */
    public function delCheck(int $id): bool|array
    {
        $exist = self::query()->where('id', $id)->first();
        if (!$exist) {
            return ['ok' => false, 'msg' => '数据不存在'];
        }

        return true;
    }

    /**
     * 删除
     *
     * @param $id
     * @return array
     */
    public function del($id): array
    {
        $rs = self::query()->where('id', $id)->delete();
        if (!$rs) {
            return ['ok' => false, 'msg' => '失败'];
        }
        return ['ok' => true, 'data' => ['rs' => $rs]];
    }

    /**
     * 列表
     *
     * @param $params
     * @return array
     */
    public function list($params): array
    {
        $page = $params['page'] ?? 1;
        $pageSize = $params['pageSize'] ?? 20;
        $where = [];
        //时间范围筛选
        if (!empty($params['startTime'])) {
            $where[] = ['created_at', '>=', $params['startTime']];
        }
        if (!empty($params['endTime'])) {
            $where[] = ['created_at', '<=', $params['endTime']];
        }

        $count = self::query()->where($where)->count();
        if ($count === 0) {
            return ['ok' => true, 'data' => [], 'msg' => '暂无数据'];
        }
        $data = self::query()->where($where)
            ->orderBy('id', 'desc')
            ->skip(($page - 1) * $pageSize)->take($pageSize)
            ->get()->toArray();

        return [
            'ok' => true,
            'data' => [
                'page' => $page,
                'pageSize' => $pageSize,
                'totalPage' => ceil($count / $pageSize),
                'totalCount' => $count,
                'data' => $data
            ]
        ];
    }

    /**
     * 导出
     *
     * @param array $params
     * @return BinaryFileResponse
     */
    public function export(array $params): BinaryFileResponse
    {
        //return Excel::download(new DemoExport($params), '测试导出.xlsx');
    }

    /**
     * 详情
     *
     * @param $id
     * @return array
     */
    public function info($id): array
    {
        $info = self::query()->where('id', $id)->first();
        if (!$info) {
            return ['ok' => false, 'msg' => '数据不存在'];
        }

        return ['ok' => true, 'data' => $info->toArray()];
    }


}
  1. 自定义 Artisan 命令 make:service, 使用 make:command 命令:

    php artisan make:command MakeServiceCommand
  2. 编写 MakeServiceCommand,核心是继承 GeneratorCommand。逻辑:读取 service.stub 并生成文件:

<?php

namespace App\Console\Commands;

use Illuminate\Console\GeneratorCommand;
use Illuminate\Support\Str;

class MakeServiceCommand extends GeneratorCommand
{
    /**
     * 命令名称和签名
     *
     * @var string
     */
    protected $signature = 'make:service {name} {--namespace=App\Service}';

    /**
     * 命令描述
     *
     * @var string
     */
    protected $description = 'Create a new service class';

    /**
     * 要生成的类的名称
     *
     * @var string
     */
    protected $name = 'make:service';

    /**
     * 获取 stub 文件的路径
     *
     * @return string
     */
    protected function getStub()
    {
        return base_path('stubs/custom/service.stub');
    }

    /**
     * 获取生成的类的命名空间
     *
     * @param string $rootNamespace
     * @return string
     */
    protected function getDefaultNamespace($rootNamespace)
    {
        return $this->option('namespace') ?: 'App\Service';
    }

    /**
     * 替换 stub 中的占位符
     *
     * @param string $stub
     * @param string $name
     * @return MakeServiceCommand
     */
    protected function replaceNamespace(&$stub, $name)
    {
        $stub = str_replace(
            ['{{ namespace }}', '{{ class }}'],
            [$this->getNamespace($name), $this->getServiceName($name)],
            $stub
        );

        return $this;
    }

    /**
     * 获取 service class name
     *
     * @param $name
     * @return string
     */
    protected function getServiceName($name): string
    {
        return Str::studly(str_replace($this->getNamespace($name) . '\\', '', $name));
    }

}
  1. 使用自定义 make:service 命令生成文件 UserService.php
    php artisan make:service UserService

小结

可以看到这里继承了框架的 \Illuminate\Console\GeneratorCommand 类,此类也是 make:controller, make:model 等相关命令实现的业务逻辑代码,扩展命令照猫画虎即可。
建议:配合系统 make:controller 命令,看一下 GeneratorCommand 的代码实现,花1小时就都清晰明了了!

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!