Customization
Hook into the status change lifecycle
Customization
The Status Management plugin lets you react to status changes through a dispatched event and through per-model lifecycle handlers.
AfterStatusChangeEvent
AfterStatusChangeEvent is dispatched after a record's status value is updated. It carries the
affected model:
namespace Beboost\StatusManagement\Events;
class AfterStatusChangeEvent
{
public function __construct(public Model $model) {}
}Listen for it like any Laravel event:
use Beboost\StatusManagement\Events\AfterStatusChangeEvent;
use Illuminate\Support\Facades\Event;
Event::listen(AfterStatusChangeEvent::class, function (AfterStatusChangeEvent $event) {
$model = $event->model; // the record whose status changed
$status = $model->status; // current Status model (or null)
if ($status?->code === 'COMPLETED') {
// send notifications, update related records, etc.
}
});The current and previous status are not passed on the event payload. Read the current status from
$event->model->status, and use the activity log if you need the previous
status (it is recorded with every transition).
Listener class
namespace App\Listeners;
use Beboost\StatusManagement\Events\AfterStatusChangeEvent;
class SendOrderStatusNotification
{
public function handle(AfterStatusChangeEvent $event): void
{
$order = $event->model;
$order->user->notify(
new OrderStatusChanged($order, $order->status)
);
}
}Register it in your EventServiceProvider:
protected $listen = [
AfterStatusChangeEvent::class => [
SendOrderStatusNotification::class,
],
];Lifecycle Handlers (before / after hooks)
To run logic before a status value is created, updated or deleted — and to be able to block the change — register a handler for a specific model. Handlers implement one or more of these contracts:
| Contract | Methods |
|---|---|
EntityStatusCreateHandler | beforeCreate(StatusValue $value): bool / afterCreate(StatusValue $value): void |
EntityStatusUpdateHandler | beforeUpdate(StatusValue $value): bool / afterUpdate(StatusValue $value): void |
EntityStatusDeleteHandler | beforeDelete(StatusValue $value): bool / afterDelete(StatusValue $value): void |
A before* method returning false (or throwing StatusInterruptProcessException) cancels the
operation and shows a danger notification to the user.
namespace App\Status;
use Beboost\StatusManagement\Models\StatusValue;
use Beboost\StatusManagement\Services\Contracts\EntityStatusUpdateHandler;
class OrderStatusHandler implements EntityStatusUpdateHandler
{
public function beforeUpdate(StatusValue $value): bool
{
// Block shipping when the order has pending payments
$order = $value->entity;
return ! ($value->status->code === 'SHIPPED' && $order->hasPendingPayments());
}
public function afterUpdate(StatusValue $value): void
{
// side effects after a successful status update
}
}Register the handler for a model — typically in a service provider's boot():
use App\Models\Order;
use App\Status\OrderStatusHandler;
use Beboost\StatusManagement\Facades\StatusManagement;
use Beboost\StatusManagement\Services\Contracts\EntityStatusUpdateHandler;
StatusManagement::register(Order::class, [
EntityStatusUpdateHandler::class => OrderStatusHandler::class,
]);Interrupt a status change
Throw StatusInterruptProcessException from a handler to stop the change with a message shown to the
user:
use Beboost\StatusManagement\Exceptions\StatusInterruptProcessException;
public function beforeUpdate(StatusValue $value): bool
{
if ($value->status->code === 'SHIPPED' && ! $value->entity->hasAddress()) {
throw new StatusInterruptProcessException('Cannot ship an order without an address.');
}
return true;
}Status Customization
Statuses can be customized through the database fields documented in Architecture and the configuration file. Key customization points:
- Visual appearance —
colorandiconfields on thestatusestable control how statuses render in badges, select fields, and charts - Behavioral flags —
is_default,initial,is_final, andrequire_commentcontrol how statuses behave during transitions - Global settings —
config('status-management.global_settings')controls icons, colors, badges, and sorting across all components. See Configuration - Lifecycle handlers — use the contracts above to inject custom logic before and after status changes
- Custom transition rules — register your own rules via
TransitionCheckerManager::register(). See Architecture
Next Steps
How is this guide?