NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

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:

Akciaexecute(…)Cesta cez fasádu
Events\CreateEventAction(CreateEventData $data): EventEvents::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\UnpublishEventActionrovnaký 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\DetachLabelsActionrovnaký tvar->labels()->detach()
Tags\SyncLabelsActionrovnaký tvar->labels()->sync()
Venues\CreateVenueAction(VenueData $data): VenueEvents::venues()->create(), ->make()->create()
Venues\UpdateVenueAction(Venue $venue, UpdateVenueData $data, ?Model $actor = null): Venuevenues()->update()
Venues\DeleteVenueAction(Venue $venue, ?Model $actor = null): voidvenues()->delete()
Venues\RestoreVenueAction(Venue $venue, ?Model $actor = null): Venuevenues()->restore()
Venues\GeocodeVenueAction(Venue $venue, bool $force = false, ?Model $actor = null): Venuevenues()->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): RsvpEvents::rsvps()->confirmPayment()
Rsvps\ReleaseHoldAction(Event $event, Rsvp|Model $who, ?Model $actor = null): Rsvp->attendees()->release(), Events::rsvps()->release()
Rsvps\RequestAdmissionPaymentAction(Rsvp $given): ?PaymentRequestEvents::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): RsvpEvents::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): RsvpEvents::invitations()->accept() / decline()
Maintenance\SweepEventsAction(?SweepOptions $options = null): SweepResultEvents::sweep()
Maintenance\RepairEventsAction(?RepairOptions $options = null): RepairReportEvents::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 kryptomien

Odoslaní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.