Each transition dispatches an event carrying the relevant model. All events live in RoundlyConsulting\Approvals\Events and expose their payload as public properties:
| Event | Payload | Fired when |
|---|---|---|
ApprovalRequested | approval | a pending decision is asked for (ask()) |
ApprovalApproved | approval | a decision is approved |
ApprovalRejected | approval | a decision is rejected |
ApprovalCancelled | approval | a decision is withdrawn (cancel()) |
ApprovalExpired | approval | a pending or approved decision lapses |
ApprovalRequestResolved | request | a request reaches approved, rejected or expired |
ApprovalToggled | actor, entity, hasBeenApproved | toggle() / toggleApproval() runs |
ApprovalStageOpened | stage | a staged request opens a stage |
ApprovalStageCleared | stage | a stage clears as approved |
ApprovalDelegated | delegation | an approver delegates authority |
ApprovalDelegationRevoked | delegation | a delegation is revoked |
ApprovalStatusChanged | subject, from, to, actor | umbrella — every status transition of a decision or request, alongside the granular event |
The umbrella event
Subscribe to ApprovalStatusChanged once to observe all transitions: a decision approved, rejected, withdrawn — including by a toggle or by a change of mind that supersedes it — or expired, and a request resolved or expired. It carries the subject (the Approval or ApprovalRequest that changed), the from and to ApprovalStatus, and the actor when one is known — null for a resolved request:
use RoundlyConsulting\Approvals\Events\ApprovalStatusChanged;
class AuditApprovalChanges
{
public function handle(ApprovalStatusChanged $event): void
{
// $event->from, $event->to, $event->subject, $event->actor
logger()->info("approval moved {$event->from->value} -> {$event->to->value}");
}
}Granular listeners
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Approvals\Events\ApprovalApproved;
use RoundlyConsulting\Approvals\Events\ApprovalRequestResolved;
Event::listen(function (ApprovalApproved $event): void {
$approval = $event->approval; // the Approval model
});
Event::listen(function (ApprovalRequestResolved $event): void {
$request = $event->request; // approved, rejected or expired — see $request->status
$subject = $request->subject; // e.g. the Release
});An ask() creates a pending decision rather than changing one, so it fires only ApprovalRequested. Stage changes and delegation also fire only their own events — not the umbrella one.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.