一个Eloquent Laravel模型上的__construct


A __construct on an Eloquent Laravel Model

我有一个自定义setter,我在我的模型上运行__construct方法。

这是我要设置的属性。

    protected $directory;

我的构造函数
    public function __construct()
    {
        $this->directory = $this->setDirectory();
    }

setter:

    public function setDirectory()
    {
        if(!is_null($this->student_id)){
            return $this->student_id;
        }else{
            return 'applicant_' . $this->applicant_id;
        }
    }

我的问题是,在我的setter中,$this->student_id(这是从数据库中提取的模型的属性)正在返回null。当我从setter中调用dd($this)时,我注意到#attributes:[]是一个空数组。
因此,直到触发__construct()之后才设置模型的属性。我怎么能设置我的$directory属性在我的构造方法?

您需要将构造函数更改为:

public function __construct(array $attributes = array())
{
    parent::__construct($attributes);
    $this->directory = $this->setDirectory();
}

第一行(parent::__construct())将在代码运行之前运行Eloquent Model自己的construct方法,它将为您设置所有属性。对构造函数的方法签名的改变是为了继续支持Laravel期望的用法:$model = new Post(['id' => 5, 'title' => 'My Post']);

经验法则是,当扩展一个类时,要始终记住,检查你没有重写一个现有的方法,这样它就不再运行了(这对于神奇的__construct__get等方法尤其重要)。您可以检查原始文件的源代码,看看它是否包含您正在定义的方法。

我不会在eloquent中使用构造函数。雄辩有办法达到你的目的。我将使用带有事件侦听器的引导方法。它看起来像这样。

protected static function boot()
{
    parent::boot();
    static::retrieved(function($model){
         $model->directory = $model->student_id ?? 'applicant_' . $model->applicant_id;
    });
}   

您可以使用的所有模型事件:retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, trashed, forceDeleted, restoring, restoredreplicating