laravel 9+ 中模型批量赋值需显式定义 $fillable 或 $guarded(10.x 要求 $guarded = ['*']),casts 中 'date' 不再返回 carbon,须改用 'datetime',模型事件应改用 observe() 注册,关系方法需严格匹配框架泛型返回类型。

模型的 $fillable 和 $guarded 在 9.x 后更严格了
升级到 Laravel 9 或更高版本后,如果模型里没显式定义 $fillable 或 $guarded,批量赋值(create()、update())会直接抛出 MassAssignmentException,而不是静默忽略——这是默认行为变更,不是你代码写错了。
常见错误现象:本地开发正常,上线后表单提交报错 add() expects parameter 1 to be array, null given 或更直白的 Class App\Models\Post contains no property $fillable(其实是没定义导致拒绝所有字段)。
- 必须在每个模型里明确声明
$fillable = ['title', 'content']或$guarded = [](后者等于全放开,不推荐) - Laravel 10 进一步收紧:连
$guarded = []都会被视为“未受保护”,需改用$guarded = ['*']才等效于“无保护”(注意是字符串'*',不是空数组) - 别依赖父类或 trait 提供的
$fillable—— PHP 不会自动合并数组属性,子类必须重写或显式继承
casts 中日期类型不再自动转 Carbon 实例(Laravel 9+)
升级后发现 $model->published_at->format('Y-m-d') 报错 “Call to a member function format() on string”,是因为 casts 里写的 'published_at' => 'date' 不再隐式转成 Carbon,只做基础类型转换(string → DateTimeImmutable)。
使用场景:需要链式调用 ->addDays()、->diffForHumans() 等方法时,必须显式指定类名。
- 改成
'published_at' => 'datetime'(返回Carbon)或'published_at' => 'immutable_datetime'(返回CarbonImmutable) - 若仍用
'date',访问时得手动封装:Carbon::parse($model->published_at) - 注意迁移兼容性:旧数据如果是 Y-m-d 格式字符串,
datetimecast 会尝试补全为当日 00:00:00;date则保持字符串,不补时间
模型事件监听器注册方式从静态方法改为服务容器绑定(Laravel 9.23+)
以前在模型里写 static::created(...) 或 boot() 里调 static::updating(...) 还能用,但升级后可能漏触发——因为 Laravel 改用容器解析模型实例时才注册监听器,静态闭包注册被绕过了。
本次升级更新内容:优化分类置顶功能处理机制;修复域名变化带来的cookie域问题;文件上传js的兼容ie9,ie10问题;更新内容编辑器版本;会员服务权限新增求购信息的发布总量限制,求购信息的每日发布量限制;新增供应信息的每日发布量限制;新增分类信息的审核机制控制;新增分类信息的每日发布量限制;新增分类信息的重发刷新功能;优化会员中心的服务类型内容;优化模板运行处理机制;优化会员商铺模板运行机制;
错误现象:本地测试没问题,队列任务或 API 测试中模型事件完全不执行。
- 统一改用
Observing:在AppServiceProvider::boot()里加\App\Models\Post::observe(\App\Observers\PostObserver::class) - Observer 类里方法名必须严格匹配:如
created()、updated()、deleting()(注意是deleting,不是deleted,后者是事后钩子,不支持取消操作) - 避免在 Observer 方法里调用
$model->save(),可能引发递归监听或事务异常
关系方法返回类型声明冲突(PHP 8.1+ + Laravel 9+)
启用了 PHP 8.1 的属性类型或返回类型后,模型关系方法如 public function author(): BelongsTo 会和 Laravel 框架内部泛型声明冲突,报错 Declaration of App\Models\Post::author() must be compatible with Illuminate\Database\Eloquent\Model::author(): Illuminate\Database\Eloquent\Relations\BelongsTo。
根本原因是 Laravel 9 的关系方法返回类型是完整命名空间路径,而你写的可能是简写或漏了泛型参数。
- 正确写法:
use Illuminate\Database\Eloquent\Relations\BelongsTo;然后public function author(): BelongsTo - 集合关系必须带泛型:
public function comments(): HasMany<comment></comment>(Comment是模型类) - 如果用 PHPStan 或 Pest 做类型检查,还要确保
composer.json里"laravel/framework": "^9.48"或更高,低版本泛型支持不全
最常被忽略的是:升级后没跑 php artisan ide-helper:models 更新 PHPDoc,IDE 里依然提示类型错误,但实际运行没问题——这容易让人误判问题根源。









