【问题标题】:Laravel Eloquent - Override Model's constructor to change attributesLaravel Eloquent - 覆盖模型的构造函数以更改属性
【发布时间】:2017-06-22 14:33:43
【问题描述】:

所以我有一个Page 模型,它扩展了Eloquent Model 类。我正在尝试覆盖构造函数,我需要一些额外的逻辑。这是我目前拥有的:

class Page extends Model
{

    public function __construct(array $attributes = [])
    {

        parent::__construct($attributes);
        $this->main_image = null;
    }

}

但是当我调用Page::find(1); 时,这似乎不会将main_image 保存到$this->attributes 属性中。

我相信这是因为Page::find 最终会调用Model::newFromBuilder,看起来像这样:

public function newFromBuilder($attributes = [], $connection = null)
{
    $model = $this->newInstance([], true);

    $model->setRawAttributes((array) $attributes, true);

    $model->setConnection($connection ?: $this->getConnectionName());

    return $model;
}

如您所见,它首先创建实例,然后设置属性,这意味着在构造函数中设置的任何内容都会被忽略。

是否有任何解决方法可以覆盖构造函数(或类似方法)以更改每个检索/创建的模型实例的属性?显然我可以覆盖newFromBuilder、newInstance、__construct 和类似的方法,但这似乎非常hacky 和不可维护。

谢谢!

【问题讨论】:

  • 所以基本上你想在创建新元素时覆盖一个参数?您应该为此使用模型事件,laravel.com/docs/5.4/eloquent#events - 特别是查看“创建/创建”。
  • 覆盖只是一个例子,可能有多个参数覆盖,它们将被包裹在 if 语句等中。我将检查事件,如果我可以将它们应用于所有类而无需编写观察者我拥有的每个模型的课程。谢谢!
  • 您的模型没有main_image 字段是否有原因?将其设置在模型中的最终目标是什么?可能有另一种解决问题的方法可能会提供更多信息,如果所有页面都有main_image,则可能会形成关系,以便您可以执行$page->mainImage->get()
  • 这背后的原因是另一个问题的潜在解决方案:stackoverflow.com/questions/44699673/…所以我想检查$page->main_image_id是否为空,将$page->main_image设置为null并且不调用关系方法

标签: php laravel eloquent


【解决方案1】:

如果您只需要能够在检索或设置时自动修改模型的属性,请使用Laravel Eloquent's Accesors and Mutators:

定义访问器

要定义访问器,请在您的模型上创建一个 getFooAttribute 方法,其中 Foo 是您希望访问的列的“经过研究”的大小写名称。在本例中,我们将为 first_name 属性定义一个访问器。在尝试检索 first_name 属性的值时,Eloquent 将自动调用访问器:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Get the user's first name.
     *
     * @param  string  $value
     * @return string
     */
    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }
}

如您所见,列的原始值被传递给访问器,允许您操作并返回该值。要访问访问器的值,您可以简单地访问模型实例上的 first_name 属性:

$user = App\User::find(1);

$firstName = $user->first_name;

定义一个修改器

要定义一个 mutator,在你的模型上定义一个 setFooAttribute 方法,其中 Foo 是你希望访问的列的“studly”大小写名称。所以,再一次,让我们为 first_name 属性定义一个 mutator。当我们尝试在模型上设置 first_name 属性的值时,将自动调用此 mutator:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Set the user's first name.
     *
     * @param  string  $value
     * @return void
     */
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }
}

mutator 将接收在属性上设置的值,允许您操纵该值并在 Eloquent 模型的内部 $attributes 属性上设置操纵值。因此,例如,如果我们尝试将 first_name 属性设置为 Sally:

$user = App\User::find(1);

$user->first_name = 'Sally';

在此示例中,将使用值 Sally 调用 setFirstNameAttribute 函数。然后,mutator 会将 strtolower 函数应用于名称并将其结果值设置在内部 $attributes 数组中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2017-07-10
    • 2013-03-22
    • 2014-06-17
    • 2018-09-24
    • 2021-05-21
    • 1970-01-01
    相关资源
    最近更新 更多