You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
        }
    );
}

问题原因说明

你之前的代码失效的核心问题:

  1. 初始状态下$this->data为null,data_set无法对null进行引用修改,必须先初始化为空数组。
  2. 即使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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:24:57