Laravel Forge部署失败:PHP7.4下User模型类型属性报错
嘿,我之前也踩过这个坑!这个报错的根源其实是PHP 7.4+的属性类型继承规则和Laravel 7底层父类的定义冲突了。
具体来说,你在App\User模型里给$fillable、$hidden、$casts这些属性加上了array类型声明,但Laravel 7自带的Illuminate\Foundation\Auth\User父类中,这些属性是没有声明类型的。按照PHP的严格规则:如果父类的属性没有类型声明,子类绝对不能给该属性添加类型声明——哪怕你指定的类型和实际运行时的类型完全一致,也会触发这个Type of ... must not be defined的致命错误。
至于为什么Homestead里运行正常?大概率是环境差异导致的:要么是Homestead的PHP版本实际低于7.4(虽然你说用PHP7.4创建项目,但可能Homestead切换了版本),要么是本地的Laravel包有特殊补丁,不过更常见的是Forge的环境严格执行了PHP的类型规则,而本地可能有某些配置绕过了检查。
接下来给你两个可行的解决办法:
方法一:移除子类属性的类型声明(最稳妥)
直接把你App\User模型里的array类型声明删掉,保持和父类一致的写法:
/** * 可批量赋值的属性 * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * 数组中应隐藏的属性 * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * 应转换为本机类型的属性 * * @var array */ protected $casts = [ 'email_verified_at' => 'datetime', ];
这样修改后,你的模型就和Laravel 7的父类定义完全兼容了,PHP不会再抛出错误。虽然失去了类型声明的静态检查,但这是Laravel 7版本下最直接的解决方式。
方法二:升级到Laravel 8+版本
如果你想保留类型声明的特性,可以考虑把项目升级到Laravel 8或更高版本。因为从Laravel 8开始,底层的Illuminate\Foundation\Auth\User类已经给这些属性添加了array类型声明,此时你在子类中添加的类型声明就会和父类保持一致,不会再触发冲突。
不过升级框架前要注意:Laravel 8有不少破坏性更新(比如路由命名空间的变化、默认模型工厂的写法改变等),记得先备份项目,并且检查第三方包是否支持Laravel 8+版本。
内容的提问来源于stack exchange,提问作者knubbe

