You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 9存储模型UUID生成方案及控制器SQL报错问题排查

问题:UUID作为URL一部分的生成位置与报错解决

我希望将UUID作为URL的一部分,示例URL如下:

https://example.com/books/fiction/don-quixote-37d8d0a6-692a-11ed-9022-0242ac120002

我尝试在BookController的store方法中生成并赋值UUID:

class BookController extends Controller
{
    public function store(BookStoreRequest $request)
    {
        $this->authorize('create', Book::class);
        
        $validated = $request->validated();
        $validated['identifier'] = (string) Str::uuid();
        
        $book = Book::create($validated);    
    }
}

但执行后出现错误:

SQLSTATE Field 'identifier' doesn't have a default value

请问应在控制器的哪个位置生成UUID?是否是identifier值未正确传递?该如何解决?


解答

1. UUID生成位置的合理性

你在store方法中生成UUID是完全可行的,这个位置没问题。报错的核心原因不是生成位置,而是identifier字段未被允许批量赋值,导致create方法过滤掉了这个字段,数据库未收到值从而触发默认值缺失错误。

2. 核心解决步骤

检查模型的批量赋值白名单

打开Book模型,确保$fillable数组中包含identifier字段:

class Book extends Model
{
    // 必须把identifier加入白名单,否则create方法会忽略该字段
    protected $fillable = [
        'title', // 示例其他字段
        'category', // 示例其他字段
        'identifier',
    ];
}

Laravel的create方法依赖$fillable来允许批量赋值,未加入的字段会被自动过滤,这就是数据库没收到identifier值的直接原因。

3. 可选优化:将UUID生成逻辑移到模型

如果希望所有创建Book实例的场景都自动生成UUID,不用在控制器重复写代码,可以把生成逻辑放到模型的creating事件中:

class Book extends Model
{
    protected static function booted()
    {
        // 模型创建前自动生成UUID
        static::creating(function ($book) {
            $book->identifier = (string) Str::uuid();
        });
    }

    protected $fillable = [
        'title',
        'category',
        'identifier',
    ];
}

这样控制器的store方法里就可以删掉$validated['identifier'] = ...这一行,代码更简洁且逻辑统一。

4. 额外检查项

  • 确认数据库中identifier字段的类型是char(36)或varchar(36),符合UUID的长度要求;
  • 如果不需要手动传入UUID,可以给数据库字段设置默认值为UUID()(MySQL 8.0+支持),但更推荐在模型层处理,保持框架逻辑统一。

内容的提问来源于stack exchange,提问作者bart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 05:05:17