DI a akcie
Fasáda je odporúčaná voľba, nie jediná cesta. Každý zápis je akcia, manažér sprístupňuje každú z nich a fasáda je skratka nad manažérom — tri vstupy, ktoré spúšťajú ten istý kód: fasáda Events (najkratší zápis); RoundlyConsulting\Events\EventsManager — koreň fasády, singleton v kontajneri — injektovaný cez konštruktor (rovnaké API, explicitná závislosť, žiadne statické volania); a akcie, final readonly triedy s jedinou metódou execute(), ktoré skladáte do vlastných úloh a príkazov:
use RoundlyConsulting\Events\Actions\Events\CancelEventAction;
use RoundlyConsulting\Events\EventsManager;
use RoundlyConsulting\Events\Facades\Events;
// Facade
Events::for($event)->by($organizer)->cancel('Venue flooded');
// Dependency injection: the same API
public function __construct(private EventsManager $events) {}
$this->events->for($event)->by($organizer)->cancel('Venue flooded');
// The raw action (no handle policy check, no fake recording)
app(CancelEventAction::class)->execute($event, actor: $organizer, reason: 'Venue flooded');
// Model traits delegate to the manager
$user->rsvp($event)->going();Injektovanie manažéra
use Illuminate\Http\Request;
use RoundlyConsulting\Events\EventsManager;
use RoundlyConsulting\Events\Models\Event;
use RoundlyConsulting\Events\Models\Rsvp;
final class JoinEventController
{
public function __construct(private EventsManager $events) {}
public function __invoke(Request $request, Event $event): Rsvp
{
// by() checks the event policy (rsvp) for the signed-in user
return $this->events->for($event)->by($request->user())
->rsvp($request->user())
->going(tier: $request->input('tier'), guests: (int) $request->input('guests', 0));
}
}Manažér je bezpečný pod Octane: nedrží kontajner a každú akciu si pri každom volaní vezme z aktuálneho, takže platí väzba, ktorú urobíte vy — alebo sandbox požiadavky.
Volanie akcie
use RoundlyConsulting\Events\Actions\Rsvps\PromoteWaitlistAction;
use RoundlyConsulting\Events\Actions\Venues\GeocodeVenueAction;
// Trusted code (a job, a command): no handle policy check and no fake recording
$promoted = app(PromoteWaitlistAction::class)->execute($event, limit: 5);
app(GeocodeVenueAction::class)->execute($venue, force: true);Priame volanie akcie preskočí kontrolu policy na handle aj zaznamenanie vo fake. Niekoľko akcií si policy overí samo, keď im odovzdáte aktéra: CreateEventAction (create a to, že organizátor aktéra povoľuje), akcie miest konania (policy miesta konania) a CheckInByCodeAction (skenovanie bez určenia podujatia). Príznak $system pri stavových akciách spustí lifecycle ako systém — to isté robí handle bez by().
Metóda fasády → akcia
49 akcií pre aplikáciu; menné priestory sú relatívne k RoundlyConsulting\Events\Actions:
| Akcia | execute(…) | Cesta cez fasádu |
|---|---|---|
Events\CreateEventAction | (CreateEventData $data): Event | Events::create(), make()->create() / ->publish() |
Events\UpdateEventAction | (Event $event, UpdateEventData $data, ?Model $actor = null, bool $silent = false): Event | ->update(), ->edit()->save() |
Events\PublishEventAction | (Event $event, ?Model $actor = null, bool $system = false, bool $silent = false): TransitionResult | ->publish() |
Events\UnpublishEventAction | rovnaký tvar | ->unpublish() |
Events\PostponeEventAction | (Event $event, ?Model $actor = null, bool $system = false, ?string $reason = null, bool $silent = false): TransitionResult | ->postpone() |
Events\RescheduleEventAction | (Event $event, CarbonInterface|string $startsAt, CarbonInterface|string|null $endsAt = null, ?string $reason = null, ?Model $actor = null, bool $system = false, bool $silent = false): Event | ->reschedule() |
Events\CancelEventAction | (Event $event, ?Model $actor = null, bool $system = false, ?string $reason = null, bool $silent = false): TransitionResult | ->cancel() |
Events\CompleteEventAction | (Event $event, ?Model $actor = null, bool $system = false, bool $silent = false): TransitionResult | ->complete() |
Events\TransitionEventAction | (Event $event, string $transition, ?Model $actor = null, bool $system = false, ?string $reason = null, array $payload = [], bool $silent = false): TransitionResult | ->transition() |
Events\MoveEventOnlineAction | (Event $event, string $url, bool $keepVenue = false, ?Model $actor = null, bool $silent = false): Event | ->moveOnline() |
Events\TransferOrganizerAction | (Event $event, Model&Organizer $organizer, bool $keepAsHost = false, ?Model $actor = null): Event | ->transferTo() |
Events\SetPosterAction | (Event $event, UploadedFile|string|null $file = null, ?string $draft = null, ?Model $actor = null): Event | ->poster() |
Events\DeleteEventAction | (Event $event, ?Model $actor = null, bool $force = false): void | ->delete() |
Events\RestoreEventAction | (Event $event, ?Model $actor = null): Event | ->restore() |
Tags\CategorizeEventAction | (Event $event, Tag|int|string|null $category, ?Model $actor = null, bool $silent = false): TagChanges | ->categorize() |
Tags\AttachLabelsAction | (Event $event, mixed $labels, ?Model $actor = null, bool $silent = false): TagChanges | ->labels()->attach() |
Tags\DetachLabelsAction | rovnaký tvar | ->labels()->detach() |
Tags\SyncLabelsAction | rovnaký tvar | ->labels()->sync() |
Venues\CreateVenueAction | (VenueData $data): Venue | Events::venues()->create(), ->make()->create() |
Venues\UpdateVenueAction | (Venue $venue, UpdateVenueData $data, ?Model $actor = null): Venue | venues()->update() |
Venues\DeleteVenueAction | (Venue $venue, ?Model $actor = null): void | venues()->delete() |
Venues\RestoreVenueAction | (Venue $venue, ?Model $actor = null): Venue | venues()->restore() |
Venues\GeocodeVenueAction | (Venue $venue, bool $force = false, ?Model $actor = null): Venue | venues()->geocode() |
Tiers\CreateTierAction | (Event $event, TierData $data, ?Model $actor = null): AdmissionTier | ->tiers()->create() / add() / make()->create() |
Tiers\UpdateTierAction | (Event $event, AdmissionTier|int|string $tier, UpdateTierData $data, ?Model $actor = null): AdmissionTier | ->tiers()->update() |
Tiers\DeleteTierAction | (Event $event, AdmissionTier|int|string $tier, ?Model $actor = null): void | ->tiers()->remove() |
Tiers\RestoreTierAction | (Event $event, AdmissionTier|int|string $tier, ?Model $actor = null): AdmissionTier | ->tiers()->restore() |
Tiers\ReorderTiersAction | (Event $event, array $order): void | ->tiers()->reorder() |
Rsvps\RespondToEventAction | (Event $event, RsvpRequest $request): Rsvp | ->rsvp($a)->going() / interested() / notGoing(), $user->rsvp($event) |
Rsvps\AddAttendeeAction | (Event $event, Model $attendee, AdmissionTier|int|string|null $tier = null, int $guests = 0, bool $overCapacity = false, ?Model $actor = null): Rsvp | ->attendees()->add() |
Rsvps\RemoveAttendeeAction | (Event $event, Rsvp|Model $who, ?Model $actor = null): Rsvp | ->attendees()->remove() |
Rsvps\ChangeTierAction | (Event $event, Rsvp|Model $who, AdmissionTier|int|string $tier, ?Model $actor = null): Rsvp | ->attendees()->changeTier() |
Rsvps\ChangeGuestsAction | (Event $event, Rsvp|Model $who, int $guests, ?Model $actor = null): Rsvp | ->attendees()->changeGuests() |
Rsvps\ConfirmRsvpAction | (Event $event, Rsvp|Model $who, ?string $reference = null, ?Model $actor = null): Rsvp | ->attendees()->confirm(), Events::rsvps()->confirm() |
Rsvps\ConfirmPaymentAction | (string $reference): Rsvp | Events::rsvps()->confirmPayment() |
Rsvps\ReleaseHoldAction | (Event $event, Rsvp|Model $who, ?Model $actor = null): Rsvp | ->attendees()->release(), Events::rsvps()->release() |
Rsvps\RequestAdmissionPaymentAction | (Rsvp $given): ?PaymentRequest | Events::rsvps()->requestPayment() |
Rsvps\PromoteWaitlistAction | (Event $event, ?int $limit = null): Collection | ->waitlist()->promote() |
CheckIns\CheckInByCodeAction | (string $input, ?Event $event = null, ?Model $by = null, ?int $guests = null, bool $ignoreWindow = false): CheckInResult | ->checkIn(), Events::checkIn() |
CheckIns\CheckInAttendeeAction | (Event $event, Rsvp|Model $who, ?int $guests = null, ?Model $actor = null): CheckInResult | ->attendees()->checkIn() |
CheckIns\UndoCheckInAction | (Event $event, Rsvp|Model $who, ?Model $actor = null): Rsvp | ->attendees()->undoCheckIn() |
CheckIns\RotateCheckInCodeAction | (Rsvp $rsvp): Rsvp | Events::rsvps()->rotateCode() |
Hosts\AddCoHostAction | (Event $event, Model&Organizer $host, ?Model $actor = null): bool | ->hosts()->add() |
Hosts\RemoveCoHostAction | (Event $event, Model $host, ?Model $actor = null): bool | ->hosts()->remove() |
Invitations\SendInvitationAction | (Event $event, Model $invitee, ?string $message = null, ?Model $actor = null): EventInvitation | ->invitations()->send() |
Invitations\RevokeInvitationAction | (Event $event, Model $invitee, ?Model $actor = null): EventInvitation | ->invitations()->revoke() |
Invitations\RespondToInvitationAction | (string $token, RsvpResponse $response = RsvpResponse::Going, ?Model $by = null, bool $system = false): Rsvp | Events::invitations()->accept() / decline() |
Maintenance\SweepEventsAction | (?SweepOptions $options = null): SweepResult | Events::sweep() |
Maintenance\RepairEventsAction | (?RepairOptions $options = null): RepairReport | Events::repair() |
- Manažér si každú akciu pri každom volaní vezme z kontajnera, takže väzba akcie vo vašej aplikácii platí pre všetky cesty — fasádu, injektovaného manažéra, handle, pod-handle, builder aj trait modelu.
- Events::fake() vymení manažéra za fasádou aj v kontajneri, takže sa podvrhne aj injektovaný EventsManager. Priame volanie akcie sa nezaznamená.
- Stavebné bloky v Actions\Internal — zmeny miest, automatické posúvanie, vypršanie rezervácií, nároky na pripomienky, vydávanie kódov, háčik pri mazaní, výpočet harmonogramu, zápisy spoluorganizátorov a podobne — sú @internal a nie sú súčasťou verejného API.
Prejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.