Laravel 变异器没有匹配的数据库列

问题描述 投票:0回答:1

我正在考虑将我的修改器和访问器更新为 Laravel 9 中引入的新语法,但我似乎无法使其工作。

我目前有一个模型,与充当键值存储的

MorphMany
对象具有
Settings
关系。作为简写,我使用变异器来设置一些更常用的设置。非常简单,看起来像这样:

class Item extends Model
    public function setSomeSettingAttribute($value)
    {
        $key = "some_setting";
        Setting::updateOrCreate(
            ["settable_id" => $this->id, "settable_type" => self::class, "key" => $key],
            ["value" => $value]
        );
    }
}

$m = Item::find(1);
// typically in a controller this would be $request->all()
$arr = ["some_setting" => 234];
$m->update($arr);

这工作正常并且设置已更新。需要注意的重要一点是,数据库中没有名为

some_setting
的列。


在新代码中,突变器看起来应该是这样的:

public function someSetting(): Attribute
{
    $key = "some_setting";
    return Attribute::make(
        set: function ($value) use ($key): void {
            Setting::updateOrCreate(
                ["settable_id" => $this->id, "settable_type" => self::class, "key" => $key],
                ["value" => $value]
            );
        }
    );
}

但这不起作用; Laravel 试图将某些内容插入到

some_setting
列中,导致 SQL“未找到列”错误。

有没有一种方法可以解决这个问题,而不需要编辑我的所有控制器代码来删除假列?或者,如果不是,旧的变元语法是否以任何方式被弃用?

php laravel eloquent mutators
1个回答
0
投票
Laravel 中的

Mutators 与强制类型转换类似,旨在在设置 Eloquent 属性值时对其进行转换。严格来说,写入数据库并不是 mutator 的工作。相反,

Attribute
的 setter 函数的结果会添加到模型的内部
$attributes
数组中。在您的情况下,由于 setter 函数没有返回任何内容,因此
'some_setting'
数组中的
$attributes
键被设置为
null
,导致 Laravel 在执行更新时尝试将
null
写入此列。

也就是说,可以返回属性名称和值的数组,如文档的改变多个属性部分中所述。当您从 setter 返回一个 empty 数组时,Laravel 会将其视为属性数组,并且根本不会向

$attributes
属性添加任何内容。这允许您应用副作用而不改变模型本身的任何属性:

public function someSetting(): Attribute
{
    $key = 'some_setting';

    return Attribute::make(
        set: function ($value) use ($key): void {
            Setting::updateOrCreate(
                ['settable_id' => $this->id, 'settable_type' => self::class, 'key' => $key],
                ['value' => $value]
            );

            return [];
        }
    );
}

通常,当您想要编辑这样的设置时,您需要定义一个

settings
关系(在本例中为 morphToMany)并执行如下更新:

$model->settings()->updateOrCreate(['key' => 'some_setting', 'value' => $value]);
© www.soinside.com 2019 - 2024. All rights reserved.