Laravel Eloquent - 重写模型的构造函数来更改属性

Gie*_*ius 4 php laravel eloquent

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

class Page extends Model
{

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

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

}
Run Code Online (Sandbox Code Playgroud)

但是当我打电话时,这似乎没有将 保存到属性main_image中。$this->attributesPage::find(1);

我相信这是因为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;
}
Run Code Online (Sandbox Code Playgroud)

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

是否有任何解决方法可以重写构造函数(或类似方法)来更改每个检索/创建的模型实例的属性?显然我可以重写newFromBuildernewInstance__construct类似的方法,但这看起来非常老套且难以维护。

谢谢!

don*_*ona 6

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

定义访问器

要定义访问器,请在模型上创建 getFooAttribute 方法,其中 Foo 是您要访问的列的“studly”大小写名称。在此示例中,我们将为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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

$firstName = $user->first_name;
Run Code Online (Sandbox Code Playgroud)

定义变异器

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

<?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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

$user->first_name = 'Sally';
Run Code Online (Sandbox Code Playgroud)

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