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
相关产品推荐
相关产品推荐

