NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Events for Laravel

Domain events

Every event is a final readonly class in RoundlyConsulting\Events\Events, implements ShouldDispatchAfterCommit — a rolled-back write dispatches nothing — and holds models. None broadcasts by itself; if you broadcast from a listener, render references, never class names.

use Illuminate\Support\Facades\Event as EventBus;   // Models\Event shadows Laravel's facade name
use RoundlyConsulting\Events\Events\AttendeeCheckedIn;
use RoundlyConsulting\Events\Events\RsvpCancelled;

EventBus::listen(RsvpCancelled::class, function (RsvpCancelled $cancelled): void {
    if ($cancelled->wasPaid) {
        // refund $cancelled->rsvp->payment_reference at your provider
    }
});

EventBus::listen(AttendeeCheckedIn::class, function (AttendeeCheckedIn $in): void {
    logger()->info('door scan', ['event' => $in->result->rsvp->event->uuid, 'first' => $in->result->firstCheckIn]);
});

Import Laravel’s facade under another name — the package’s Models\Event shadows Event. Listeners see the committed rows.

EventPayloadWhen
EventCreatedEvent $event, ?Model $actorCreated (a draft).
EventUpdatedEvent $event, list<string> $changed, ?Model $actor, bool $silentFields changed (category, labels for tag changes).
EventDeleted / EventRestoredEvent $event, ?Model $actor (+ bool $force)—
EventPublished / EventUnpublished / EventCompletedEvent $event, ?Model $actor—
EventPostponed / EventCancelledEvent $event, ?string $reason, ?Model $actor, bool $silent (+ list $releasedHolds)releasedHolds: the RSVPs whose holds the cancellation released.
EventRescheduledEvent $event, CarbonImmutable $previousStartsAt, ?string $reason, ?Model $actor, bool $silent—
EventMovedOnlineEvent $event, ?Model $actor, bool $silentAn announced event moved online (never a draft).
EventStatusChangedEvent $event, ?string $transition, $from, $to, ?Model $actor, bool $silentEvery status change.
OrganizerTransferredEvent $event, Model $from, Model $to, ?Model $actor—
PosterChangedEvent $event, ?Media $poster, ?Model $actorSet or removed.
VenueCreated / VenueDeleted / VenueRestored · VenueUpdatedVenue $venue, ?Model $actor (+ list<string> $changed)—
VenueGeocoded / VenueGeocodingFailedVenue $venue—
TierCreated / TierDeleted / TierRestored · TierUpdatedAdmissionTier $tier, ?Model $actor (+ list<string> $changed)—
RsvpChangedRsvp $rsvp, ?RsvpStatus $from, ?Model $actorEvery RSVP status change.
AttendeeConfirmedRsvp $rsvp, bool $lateEntered going (late: a payment after the hold expired).
AttendeeWaitlisted / AttendeePromoted / RsvpHoldExpiredRsvp $rsvp—
RsvpHeldRsvp $rsvp, Money $amount, ?PaymentRequest $paymentRequestA paid seat is held — with a checkout the package stored, or none (collect another way).
RsvpPaymentRequestDiscardedRsvp $rsvp, PaymentRequest $paymentRequestA checkout for a hold that changed meanwhile — void it at your provider.
RsvpPaymentRequestFailedRsvp $rsvp, Throwable $exceptionThe collector threw.
RsvpCancelledRsvp $rsvp, bool $wasPaidSomeone with seats left — refund the paid ones.
AttendeeCheckedIn · CheckInUndoneCheckInResult $result · Rsvp $rsvp, ?Model $actorA first scan or a manual check-in · an undo.
CoHostAdded / CoHostRemovedEvent $event, Model $host, ?Model $actor—
InvitationSentEventInvitation $invitation, string $token, ?string $messageSent or re-sent — and again, with a fresh token, for each pending invitation of a draft when it is published. Keep the token out of logs; encrypt queued listeners.
InvitationAccepted · InvitationDeclined · InvitationRevokedEventInvitation $invitation (+ Rsvp $rsvp · + ?Model $actor)—
RemindersDispatchedEvent $event, string $offset, int $recipientsThe sweep sent one reminder offset.
  • The package listens to lifecycle’s LifecycleTransitioning and LifecycleTransitioned — the sequence, the cancellation effects, the phase events above — and to its own events for the notices. Fake only the events you assert; Testing explains why.
  • InvitationSent carries the plain token: keep it out of logs and encrypt queued listeners (ShouldBeEncrypted).

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 crypto

By 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.