在模型中使用引导方法时,SoftDeletes 不过滤

SoftDeletes do not filter when using a boot method in a model

我有一个 Model 在 Laravel 中使用软删除,并且还使用了一个包含 boot 函数的特征:

class Design extends Model {
    uses Softdeletes, Versionable;
    // ...
}

trait Versionable {
    public static function boot(){
    // ...
    }
}

SoftDeletes 本身仍然有效:deleted_at 列正在正确填充。但是,Designs::get() 没有正确过滤软删除模型:

return Designs::get();

[{"id":1,"project_id":1,"name":"","description":null,"created_at":"2015-12-04 21:06:40","updated_at":"2015-12-04 21:06:40","deleted_at":null},
 {"id":2,"project_id":1,"name":"A Design","description":"a different description", "created_at":"2015-12-04 21:06:57","updated_at":"2015-12-04 21:07:09","deleted_at":"2015-12-04 21:07:09"}]

从 Versionable 中删除 Versionable 特征或 boot 方法可以解决问题。

为什么会发生这种情况,我该如何解决?

首先,我假设您没有在特征的 boot 方法中调用 parent::boot();,这就是您遇到此问题的原因。您正在覆盖父级的引导方法。但是,出于某些原因我不推荐这种方法,并且 Laravel 实际上在向特征添加引导方法时推荐标准命名约定。

如果您的特征有一个 boot 方法,它将覆盖父模型的 boot 方法。您可以将 parent::boot(); 方法添加到特征的 boot 方法来修复此问题,以便它也将调用父级的 boot 方法。然而,如果你的模型有一个 boot 方法,它基本上会删除特征的引导方法。向您的特征添加引导方法会产生潜在的冲突,无论是现在、以后还是其他人试图使用您的特征。

为了解决这个问题,Laravel建议您按以下格式命名特征的引导方法:boot{TraitName}.

换句话说,你的 Trait 被称为 Versionable 所以如果你将引导方法重命名为这个,你的代码将工作:

public static function bootVersionable(){
    // ...
}

编辑:Source

If an Eloquent model uses a trait that has a method matching the bootNameOfTrait naming convention, that trait method will be called when the Eloquent model is booted, giving you an opportunity to register a global scope, or do anything else you want.