Eloquent Laravel模型的__construct

Nat*_*ala 17 php laravel eloquent

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

这是我想要设置的属性.

    protected $directory;
Run Code Online (Sandbox Code Playgroud)

我的构造函数

    public function __construct()
    {
        $this->directory = $this->setDirectory();
    }
Run Code Online (Sandbox Code Playgroud)

二传手:

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

我的问题是,在我的setter里面,$this->student_id(这是从数据库中提取的模型的属性)正在返回null.当我dd($this)来自我的二传手时,我注意到我的#attributes:[]是一个空阵列.
因此,模型的属性在__construct()触发之后才会设置.如何$directory在构造方法中设置属性?

ale*_*ell 66

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

public function __construct(array $attributes = array())
{
    parent::__construct($attributes);

    $this->directory = $this->setDirectory();
}
Run Code Online (Sandbox Code Playgroud)

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

经验法则真的是要永远记住,扩展一个类时,要检查你没有覆盖现有的方法,使其不再运行(这是与魔法尤其重要__construct,__get等方法).您可以检查原始文件的来源,看它是否包含您定义的方法.


Jed*_*nch 11

我永远不会在雄辩中使用构造函数。Eloquent 有办法实现你想要的。我将使用带有事件侦听器的引导方法。它看起来像这样。

protected static function boot()
{
    parent::boot();

    static::retrieved(function($model){
         $model->directory = $model->student_id ?? 'applicant_' . $model->applicant_id;
    });
}   
Run Code Online (Sandbox Code Playgroud)

以下是您可以使用的所有模型事件:retrievedcreatingcreatedupdatingupdatedsavingsaveddeletingdeletedtrashedforceDeletedrestoring、 、restoredreplicating