It took me some time to figure out the right way to define, fire and listen for custom events for a Laravel model using a trait, so I’m writing down how I did it in case it’s helpful to others.
Let’s say you have a model Post
that you set up as having a “draft” status by default, but eventually will have a status of “publish”. Let’s also say you want to make the act of publishing a post a custom model event that can be listened for in addition to the standard model events like “created” or “updated”. And let’s say you want to do all of this using a trait so that you can apply the same logic to another model in the future, such as comments on the post, without repeating yourself.
Here’s what my Post model might look like:
<?php
namespace App\Models;
class Post extends Model
{
//
}
Let’s create a Publishable
trait that can be applied to this model:
<?php
namespace App\Models\Traits;
trait Publishable
{
// Add to the list of observable events on any publishable model
public function initializePublishable()
{
$this->addObservableEvents([
'publishing',
'published',
]);
}
// Create a publish method that we'll use to transition the
// status of any publishable model, and fire off the before/after events
public function publish()
{
if (false === $this->fireModelEvent('publishing')) {
return false;
}
$this->forceFill(['status' => 'publish'])->save();
$this->fireModelEvent('published');
}
// Register the existence of the publishing model event
public static function publishing($callback)
{
static::registerModelEvent('publishing', $callback);
}
// Register the existence of the published model event
public static function published($callback)
{
static::registerModelEvent('published', $callback);
}
}
This new trait can now be applied to the Post
model: