在 trait 中定义
__constructor
实际上是错误的,或者说是不好的设计。
构造函数应该特定于它们所属的类,而不是 trait。另一个问题是,在 Model 类中导入 trait,这意味着您应该特别遵循有关
在模型中加载 trait的规则。
在模型的引导阶段,它会递归地搜索类中导入的 trait,并自动调用使用
boot{TraitNameHere}
命名约定的方法(静态方式)。这证明了模型中的 trait 不涉及 Laravel 的依赖注入周期。
要实现这一点,您可以使用 Laravel 全局帮助程序,将存储在容器中的实例加载到静态属性中,如门面
App::make(DefinedKeyHere)
。然后将分配的实例存储在静态属性中,以使其保留到运行时结束,并且因为召回方法是
static
。
trait TimezoneTrait
{
protected static $userRepository;
protected static function bootTimezoneTrait()
{
static::$userRepository = \App::make(UserRepositoryInterface::class);
}
}
如果您当前正在尝试避免使用全局助手,监听模型引导事件也是有帮助的。在EventServiceProvider内的示例:
Event::listen('eloquent.booting:*', function (Model $model) {
$model->setUserRepository($this->app[UserRepositoryInterface::class]);
});
那么这个特征就是:
trait TimezoneTrait
{
protected static $userRepository;
public function static setUserRepository(UserRepositoryInterface $userRepository)
{
static::$userRepository = $userRepository;
}
}
请注意,我将setUserRepository
定义为静态的,但您也可以将其定义为非静态的。
稍微扩展一下有关模型事件的内容,每当模型执行其相关操作时,它都会触发几个事件。
Laravel 5.5的示例事件:
public function getObservableEvents()
{
return array_merge(
[
'creating', 'created', 'updating', 'updated',
'deleting', 'deleted', 'saving', 'saved',
'restoring', 'restored',
],
$this->observables
);
}
当其实例化(也被反序列化)时,还会触发另外两个默认事件,即booting
和booted
。使用的方法是触发事件,注意事件名称。
protected function fireModelEvent($event, $halt = true)
{
// ...
return ! empty($result) ? $result : static::$dispatcher->{$method}(
"eloquent.{$event}: ".static::class, $this
);
}
protected $userRepository;
可能会起作用。 - Jagruti Metaliyause
的类一起注入。但是,没有什么可以阻止你在注入另一个类的类中使用该特质。 - Andrei