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

发布于 2025-01-25 16:20:32 字数 1451 浏览 2 评论 0 原文

我正在寻找将突变器和登录器更新为中引入,但我似乎无法使其起作用。

我目前有一个与 morphmany 设置的关系对象的模型,该模型充当键值存储。作为速记,我正在使用突变器来设置一些更常用的设置。非常简化,看起来像这样:

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“未找到”错误。

有没有办法解决此问题,不涉及编辑我所有的控制器代码以删除伪造的列?或者,如果没有,旧的突变器语法是否以任何方式贬低了?

I'm looking at updating my mutators and accessors to the new syntax introduced in Laravel 9 but I can't seem to make it work.

I currently have a model with a MorphMany relationship to a Settings object that acts as a key-value store. As a shorthand I'm using mutators to set a couple of more commonly used settings. Very simplified, it looks like this:

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

This works fine and the setting is updated. The important thing to note is that there is no column in the database named some_setting.


In the new code, it seems like the mutator should look like this:

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

But this is not working; Laravel is attempting to insert something into the some_setting column, resulting in an SQL "column not found" error.

Is there a way around this that doesn't involve editing all my controller code to remove the fake columns? Or, if not, is the old mutator syntax deprecated in any way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

像极了他 2025-02-01 16:20:32

laravel中的突变器,类似于演员设置雄辩的属性值。严格来说,写入数据库不是突变器的工作。相反,属性的设置器功能的结果将添加到模型的内部 $属性 array。在您的情况下,由于setter函数没有返回任何内容,'some_setting'键键 array设置为 null ,执行更新时,导致Laravel尝试将 null 写入本列。

也就是说,如突变文档的多个属性。当您从设置器返回 empty 数组时,Laravel将将其视为属性数组,并且根本不会将任何内容添加到 $属性属性中。这使您可以在不更改模型本身的任何属性的情况下应用副作用:

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

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

            return [];
        }
    );
}

但是,通常,当您要编辑这样的设置时,您将定义 settings 关系( morphmany 在这种情况下)并执行这样的更新:

$model->settings()->updateOrCreate(['key' => 'some_setting'], ['value' => $value]);

Mutators in Laravel, similar to casts, are meant to transform an Eloquent attribute value when it is set. Strictly speaking, it is not the job of a mutator to write to the database. Rather, the result of an Attribute's setter function gets added to the model's internal $attributes array. In your case, since the setter function didn't return anything, the 'some_setting' key in the $attributes array was set to null, causing Laravel to attempt writing null to this column when performing the update.

That said, it is possible to return an array of attribute names and values, as described in the Mutating Multiple Attributes section of the documentation. When you return an empty array from the setter, Laravel will treat this as an array of attributes, and it won't add anything to the $attributes property at all. This allows you to apply side effects without altering any attribute on the model itself:

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

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

            return [];
        }
    );
}

Typically though, when you want to edit a setting like this, you'd define a settings relationship (morphMany, in this case) and perform the update like this:

$model->settings()->updateOrCreate(['key' => 'some_setting'], ['value' => $value]);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文