Laravel 11中自定义JSON属性的读写实现问题
解决Laravel 11中JSON字段属性的Attribute访问问题
步骤1:配置字段类型转换
首先在Service模型中添加$casts属性,让Laravel自动将data JSON字段转换为数组,省去手动解析JSON的操作:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Service extends Model { protected $casts = [ 'data' => 'array', ]; // 其他模型逻辑... }
步骤2:实现Attribute访问器与修改器
针对name、style等嵌套在data中的属性,使用Laravel 11的Attribute类编写对应的访问器和修改器。以name为例:
use Illuminate\Database\Eloquent\Casts\Attribute; /** * 获取或设置服务名称 */ protected function name(): Attribute { return Attribute::make( // 访问器:从data数组中读取name值,不存在则返回null get: fn () => data_get($this->data, 'name'), // 修改器:更新data数组中的name值,并同步回模型属性 set: function (string $value) { // 确保data是数组(避免初始状态为null的情况) $data = $this->data ?? []; // 修改数组中的name键 data_set($data, 'name', $value); // 将更新后的数组赋值回模型,让Laravel感知到变化 $this->data = $data; } ); }
同理,为style、priority、icon等属性编写相同结构的方法即可:
protected function style(): Attribute { return Attribute::make( get: fn () => data_get($this->data, 'style'), set: function (string $value) { $data = $this->data ?? []; data_set($data, 'style', $value); $this->data = $data; } ); }
问题原因说明
你之前的代码失效的核心问题:
- 初始状态下
$this->data为null,data_set无法对null进行引用修改,必须先初始化为空数组。 - 即使
data_set修改了数组,也需要将更新后的数组重新赋值给$this->data,确保模型能感知到属性变化,这样在save()时才会同步到数据库。
测试验证
现在可以按照你期望的方式操作模型:
// 创建并保存服务 $s = new Service(); $s->name = 'My service'; $s->style = 'primary'; $s->save(); // 查询并读取属性 $s = Service::find(1); echo $s->name; // 输出:My service echo $s->style; // 输出:primary
内容的提问来源于stack exchange,提问作者Tales
相关产品推荐
相关产品推荐

