So the way I see it is that a good Laravel application should be very model- and event-driven.
I have a Model called Article. I wish to send email alert
Laravel 6, the shortest solution
BaseSubscriber class
namespace App\Listeners;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Str;
/**
* Class BaseSubscriber
* @package App\Listeners
*/
abstract class BaseSubscriber
{
/**
* Returns the first part of an event name (before the first dot)
* Can be a class namespace
* @return string
*/
protected abstract function getEventSubject(): string;
/**
* Register the listeners for the subscriber.
* @param Dispatcher $events
*/
public function subscribe($events)
{
$currentNamespace = get_class($this);
$eventSubject = strtolower(class_basename($this->getEventSubject()));
foreach (get_class_methods($this) as $method) {
if (Str::startsWith($method, 'handle')) {
$suffix = strtolower(Str::after($method, 'handle'));
$events->listen("$eventSubject.$suffix", "$currentNamespace@$method");
}
}
}
}
OrderEventSubscriber class. Handlers for Order model events
use App\Models\Order;
/**
* Class OrderEventSubscriber
* @package App\Listeners
*/
class OrderEventSubscriber extends BaseSubscriber
{
/**
* @return string
*/
protected function getEventSubject(): string
{
return Order::class; // Or just 'order'
}
/**
* @param Order $order
*/
public function handleSaved(Order $order)
{
// Handle 'saved' event
}
/**
* @param Order $order
*/
public function handleCreating(Order $order)
{
// Handle 'creating' event
}
}
ModelEvents trait. It goes to your models, in my case - App\Model\Order
namespace App\Traits;
use Illuminate\Database\Eloquent\Model;
/**
* Trait ModelEvents
* @package App\Traits
*/
trait ModelEvents
{
/**
* Register model events
*/
protected static function bootModelEvents()
{
foreach (static::registerModelEvents() as $eventName) {
static::$eventName(function (Model $model) use ($eventName) {
event(strtolower(class_basename(static::class)) . ".$eventName", $model);
});
}
}
/**
* Returns an array of default registered model events
* @return array
*/
protected static function registerModelEvents(): array
{
return [
'created',
'updated',
'deleted',
];
}
}
Register the subscriber in a service provider, e.g AppServiceProvider
/**
* @param Dispatcher $events
*/
public function boot(Dispatcher $events)
{
$events->subscribe(OrderEventSubscriber::class);
}
How just add the ModelEvents trait into your model, adjust the events you want to register instead of default ones:
protected static function registerModelEvents(): array
{
return [
'creating',
'saved',
];
}
Done!