所以我有一个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;
}
因此,您可以看到它首先创建实例然后设置属性,这意味着构造函数中设置的任何内容都会被忽略。
是否有任何解决方法可以覆盖构造函数(或类似方法)来更改每个检索/创建的模型实例的属性?显然,我可以覆盖newFromBuilder
,newInstance
,__construct
和类似的方法,但这看起来非常黑客且无法维护。
谢谢!
答案 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数组中。