解锁 Laravel 代码生成(第 3 部分):从数据库架构中自动验证

PHP

为什么要实现代码生成自动化?

手动编写代码,尤其是像CRUD(创建、读取、更新、删除)和验证这类样板代码,既耗时又重复,还容易出现人为错误。将自动化融入工作流程后,你将获得以下好处:

  • 保持同步:无论何时在数据库中添加或删除列,只需一个命令就能重新生成代码。
  • 提高一致性:每个生成的文件都遵循统一的结构和编码标准。
  • 减少人工劳动:将精力集中在应用程序的独特功能上,而不是重复的任务。
  • 节省时间:在添加或修改列时减少重复的样板代码。

提取数据库模式

实现自动化的第一步是提取数据库模式。我们要将表定义转换为JSON文件,这种格式易于阅读、修改,并且方便用于代码生成过程。

将模式提取为JSON

第一步是将表信息(如列和索引)提取到一个JSON文件中。以下是一段简短的代码片段(来自我在较大项目中使用的TableUtils类,关注我以获取未来项目及更新信息!),展示了如何获取给定表的列信息:

// TableUtils代码片段
public function getTableInfo(): Collection
{
    // 确保表存在
    if (!Schema::hasTable($this->table)) {
        throw new \Exception("表 {$this->table} 未找到");
    }

    $columns = Schema::getColumns($this->table);

    return collect([
       'model'   => Str::studly(Str::singular($this->table)),
        'table'   => $this->table,
        'columns' => $columns,
    ]);
}

然后,将这个集合转换为JSON并保存到一个文件中,比如schema/categories.json。(这样就无需每次都进行查询)

{
  "model": "Category",
  "table": "categories",
  "columns": [
    {
      "name": "id",
      "type": "bigint(20) unsigned",
      "nullable": false
    },
    {
      "name": "name",
      "type": "varchar(255)",
      "nullable": false
    },
    {
      "name": "created_at",
      "type": "timestamp",
      "nullable": true
    },
    {
      "name": "updated_at",
      "type": "timestamp",
      "nullable": true
    }
  ]
}

最小化表单请求存根

接下来,我们创建一个表示Laravel中表单请求的小存根,这是我们在第一部分学到的内容:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class Store{{modelName}}Request extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            {{validationRules}}
        ];
    }
}

自动生成验证规则

这里有一个小命令,它读取JSON文件,分析每一列,并将适当的验证规则注入到存根中,这是我们在第二部分学到的将存根和命令结合的方法:

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;

class GenerateValidation extends Command
{
    protected $signature = 'generate:validation {table}';
    protected $description = '从表模式JSON生成表单请求验证文件';

    public function handle()
    {
        $table = $this->argument('table');
        $schemaPath = base_path("schema/{$table}.json");

        if (! File::exists($schemaPath)) {
            $this->error("表 [{$table}] 的模式JSON在以下路径未找到: {$schemaPath}");
            return;
        }

        // 加载模式
        $schema = json_decode(File::get($schemaPath), true);

        // 加载我们的存根
        $validationStub = File::get(base_path('stubs/validation.stub'));

        // 根据列构建规则
        $rules = collect($schema['columns'])->map(function ($column) {
            $ruleParts = [];

            // 必填或可为空
            $ruleParts[] = $column['nullable']? 'nullable' :'required';

            // 字符串的简单示例
            if (preg_match('/varchar\((\d+)\)/', $column['type'], $matches)) {
                $maxLength = $matches[1];
                $ruleParts[] ='string';
                $ruleParts[] = "max:{$maxLength}";
            }

            // 可以针对其他类型(如整数、日期)进行扩展
            return "'{$column['name']}' => '". implode('|', $ruleParts). "'";
        })->implode(",\n            ");

        // 将规则插入存根
        $validationStub = str_replace('{{modelName}}', $schema['model'], $validationStub);
        $validationStub = str_replace('{{validationRules}}', $rules, $validationStub);

        // 保存到app/Http/Requests目录
        $filename = "Store{$schema['model']}Request.php";
        File::put(app_path("Http/Requests/{$filename}"), $validationStub);

        $this->info("为 [{$schema['model']}] 创建的验证文件: {$filename}");
    }
}

它的工作原理如下:

  1. 加载JSON:我们获取表的模式文件(例如categories.json)。
  2. 解析列:分析每一列,查看它是否可为空或是否为varchar(x)类型。
  3. 构建规则字符串:例如,一个不可为空的varchar(255)将变为required|string|max:255。
  4. 注入到存根:占位符{{validationRules}}被替换为构建好的规则字符串。
  5. 生成文件:最终生成的StoreCategoryRequest.php文件可在Laravel应用程序中使用。

为什么这很重要

  1. 节省时间:你再也无需手动输入required|string|max:255这类内容。
  2. 防止错误:对数据库的更改只需一键操作就能同步到验证规则中。
  3. 易于扩展:添加针对整数、日期或枚举的逻辑,无论哪种适合你的模式。

展望未来

这只是冰山一角。一旦你熟悉了模型、控制器和验证的自动化,你可以进一步扩展到:

  1. 视图生成:使用你的模式生成用于列出、创建、编辑和查看记录的Blade模板。
  2. API资源:根据你的模式自动构建API控制器、路由和资源类。
  3. 关系:整合外键数据以自动生成hasOne、hasMany、belongsTo等关系。

目前,这里概述的方法为自动化Laravel开发工作流程的大部分内容提供了强大的基础。

结论

通过利用数据库模式生成验证规则,你朝着完全自动化的代码生成管道又迈进了一步。你可以应用相同的原则来构建模型、控制器等,从而获得一个健壮、可扩展且易于维护的开发过程。

要点总结

  1. 集中验证:使表单请求始终与实际数据库保持一致。
  2. 尽量减少手动维护:每当列发生变化时重新生成,让脚本完成繁重的工作。
  3. 根据需要扩展:随着应用程序的增长,为更多数据类型(如整数、小数、日期)添加规则。

通过这种设置,你再也无需在多个地方跟踪列的变化,数据库模式成为唯一的事实来源。祝编码愉快,愿你的所有验证都准确无误!

Php
Publish on 2025-01-09,Update on 2025-02-10