PHP 7.2 + Laravel 5.8:对使用Trait定义的父方法的调用被使用该Trait的类中对父方法的调用所覆盖

时间:2019-06-12 00:47:43

标签: php laravel

可能很难通过标题来解释这种情况,所以让我放在这里。

我不得不使用Laravel Boilerplate。它对模型使用UUID。它有一个trait,在创建用户模型时会添加UUID。

protected static function boot() // this is in the trait
{
    parent::boot();

    static::creating(function ($model) {
        $model->{$model->getUuidName()} = PackageUuid::generate(4)->string;
    });
}

我的口才User使用此特征。一切正常,但是有一天我不得不将全局范围添加到User ,所以我在User类中定义了

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

    static::addGlobalScope(new UserScopeSalesContactAdmin());
}

enter image description here

我完全错过了。现在,我的全局作用域起作用了,但是UUID被忽略了。 我显然知道为什么会这样。我不是Boilerplate的作者,我将以不同的方式来构建它,但这是一个很好的教育案例,因此我的问题是:

如何更改我的全局作用域和UUID的工作方式?我可以简单地将addGlobalScope移至特征,但这显然是愚蠢的想法,因为作用域具有与UUID无关,因此违反了OOP规则。

编辑:

我做了另一种方法:复制:

static::creating(function ($model) {
     $model->{$model->getUuidName()} = PackageUuid::generate(4)->string;
});

转到boot中的User方法,但是我仍然认为这是重复的…

2 个答案:

答案 0 :(得分:0)

您可以编写自己的特征。但是请定义boot()而不是boot<TraitName>()

trait HasUuid
{
    protected static function bootHasUuid()
    {
        static::creating(function ($model) {
            $model->{$model->getUuidName()} = PackageUuid::generate(4)->string; 
        });
    }
}

通过这种方式,您无需覆盖boot()

Laravel将基于上述命名方案调用特质的特殊启动方法。只是没有充分记录的功能...

答案 1 :(得分:0)

您可以在假设特征名称为BoilerplateTrait的情况下尝试此操作。从用户模型的启动功能中调用BoilerplateTrait启动功能

protected static function boot()
{
    //parent::boot();
    BoilerplateTrait::boot();
    static::addGlobalScope(new UserScopeSalesContactAdmin());
}