I have a Model
that uses soft-deletes in Laravel, and that also uses a trait that includes a boot
function:
class Design extends Model {
uses Softdeletes, Versionable;
// ...
}
trait Versionable {
public static function boot(){
// ...
}
}
SoftDeletes themselves still work: the deleted_at column is being filled properly. However, Designs::get()
doesn't filter the soft deleted models properly:
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"}]
Removing either the Versionable
trait or the boot
method from Versionable fixes the problem.
Why does this happen, and how can I fix it?
First, I'm going to assume that you are not calling parent::boot();
in your trait's boot
method, which is why you are getting this problem. You are overriding the parent's boot method. However, I wouldn't recommend this approach for a few reasons, and Laravel actually recommends a standard naming convention when it comes to adding a boot method to your trait.
If your trait has a boot
method, it will override the parent model's boot
method. You can add a parent::boot();
method to the trait's boot
method to fix this so that it will call the parent's boot
method as well. However, if your model has a boot
method, it'll basically erase the trait's boot method. Adding a boot method to your trait creates potential conflicts whether it's now, later on down the road, or if someone else tries to use your trait.
In order to counter this problem, Laravel recommends that you name the trait's boot method in the following format: boot{TraitName}
.
In other words, your Trait is called Versionable
so your code will work if you rename the boot method to this:
public static function bootVersionable(){
// ...
}
Edit: 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.