不要在模型 Trait 里写 boot () 方法
TL;DR 在一个 trait 模型中使用 bootNameOfTrait()
代替 boot()
来避免被基础模型的 boot()
方法覆盖。
通过一个 boot 方法添加行为
打比方对于每个模型你有一个 HasImage
trait ,与一个图片相关:
trait HasImage
{
public function image()
{
return $this->belongsTo(Image::class);
}
}
并且你需要确保模型删除的时候,图片被删除,所以你在 trait 中添加了一个 boot()
方法。
无论模型何时初始化,静态
boot()
方法自动执行,所以它是一个添加行为或者绑定事件的理想所在。比如,在我们当前的案例中,模型中发生删除事件时自动删除一个相关图片。
public static function boot()
{
// 如果存在的话,删除关联图片
static::deleting(function ($model) {
$model->image->delete();
});
}
然而,如果父模型也含有 boot()
方法的话,trait 方法会被覆盖。
解决方案? 使用 bootHasImage()
代替 boot()
一个更好的办法
trait HasImage
{
public static function bootHasImage()
{
// 如果存在,删除关联图片
static::deleting(function($model) {
$model->image->delete();
});
}
public function image()
{
return $this->belongsTo(Image::class);
}
}
如此行之有效是因为来自 Eloquent’s Model.php
的一小段.
protected static function boot()
{
static::bootTraits();
}
/**
* 启动模型的所有可启动 trait
*
* @return void
*/
protected static function bootTraits()
{
$class = static::class;
foreach (class_uses_recursive($class) as $trait) {
if (method_exists($class, $method = 'boot' . class_basename($trait))) {
forward_static_call([$class, $method]);
}
}
}
现在我们气贯长虹,找到了在模型事件中,在特定的 trait 中,加入钩子的方法。
希望你能喜欢!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
相见恨晚的功能!
这个之前
use SoftDeletes;
时知道了也可以 在boot方法中 parent::boot();
这个很实用,不用 parent::boot () 了