laravel 11/12中访问器的遇到的问题
太久没接触laravel,之前公司的项目还是5.6的时代,现在最新的是12了,访问器的写法有改变了:
*/
protected $appends = [
'price_with_tax', // 5. 将新属性的名称添加到这里
];
// ... priceWithTax() 方法 ...
protected function priceWithTax(): Attribute
{
return Attribute::make(
get: fn ($value, $attributes) =>
round($attributes['price'] * (1 + $attributes['tax_rate']), 2)
);
}
结果我得到的响应是:
`"grade_level": {
"get": {},
"set": null,
"withCaching": false,
"withObjectCaching": true
}`
不符合预期。
经过一翻查找,得出问题的原因。
之前看到的输出是 Attribute 对象本身的序列化结果,而不是它计算后的值。
问题的原因几乎可以肯定是:访问器方法声明为了 public,而它必须是 protected。
为什么必须是 protected?
在 Laravel 中,Eloquent 的魔术属性访问机制有特定的工作流程。当您使用新的 Attribute 风格定义访问器时:
如果方法是 protected:Laravel 会识别出这是一个特殊的属性定义。当您访问 $model->grade_level 时,Laravel 不会直接返回 Attribute 对象,而是会调用其内部的 get 回调函数,并将计算结果作为属性的值。
如果方法是 public:Laravel 会将其视为一个普通的公共方法。当魔术属性访问机制查找 grade_level 时,它会找到一个同名的公共方法 gradeLevel(),直接调用它,然后将该方法的返回值(也就是那个 Attribute 对象本身)赋给 grade_level 属性。因此,在序列化时,您看到的就是这个 Attribute 对象的内部结构。