Laravel Eloquent - 覆盖Model的构造函数来更改属性

时间:2017-06-22 14:33:43

标签: php laravel eloquent

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

class Page extends Model
{

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

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

}

但是,当我致电main_image时,这似乎并未将$this->attributes保存到Page::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;
}

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

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

谢谢!

1 个答案:

答案 0 :(得分:0)

如果您只需要在检索或设置时自动修改模型的属性,那么请使用Laravel Eloquent's Accesors and 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);
    }
}

如您所见,列的原始值将传递给访问者,允许您操作并返回值。要访问访问者的值,您只需访问模型实例上的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数组中。