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

Kým ho nezapnete, je vypnuté:

EVENTS_ROUTES=on
  • Prefix events.routes.prefix (api), názvy rout events.*, middleware events.routes.middleware (['api', 'throttle:events-api']); zapisovacie routy pridajú events.routes.auth_middleware (['auth']).
  • Nenastavený prepínač zostáva vypnutý — aj v publikovanej konfigurácii, ktorej pole routes kľúč nemá, pretože zlučovanie je plytké.
  • Ak chcete upraviť súbor rout, publikujte --tag=events-routes: keď routes/events.php vo vašej aplikácii existuje, načíta sa namiesto súboru balíka a prepínač ho naďalej riadi.
  • Zápisy vždy vyžadujú prihláseného používateľa. Po vašom auth_middleware spustí každá zapisovacia routa vlastnú kontrolu balíka: chýbajúci prihlásený používateľ alebo používateľ guardu, ktorý nie je Eloquent model, je 401 — aj pri auth_middleware = []. Beží pred validáciou, takže hosť sa nikdy nedozvie tvar požiadavky. Čítacie routy a routy odkazu z pozvánky hostí naďalej pustia.

Konvencie

  • {event} je uuid — obmedzené tak, aby sa naň /events/feed.ics nikdy nedostal — a podujatie, ktoré volajúci vidieť nesmie, je 404 presne ako neexistujúce, na každom endpointe. {rsvp} a {tier} sú obmedzené na podujatie (typ vstupenky podľa id alebo kľúča); {venue} je číselné.
  • Na vaše modely sa API odvoláva cez alias, nikdy cez názov triedy: {type: user, id: 42} v telách a user:42 v cestách a filtroch (events.organizers, events.attendees). V tele je každé zlyhanie — neznámy alias, chybný kľúč, chýbajúci riadok — rovnaké 422 unknown_alias.
  • Časy v požiadavkách sú miestny čas v pásme podujatia alebo okamih ISO-8601 s posunom; odpovede používajú ISO-8601 s vlastným posunom podujatia.
  • Textové polia prijímajú reťazec (aktuálny jazyk) alebo mapu jazykov. Ceny sú desatinné reťazce s voliteľnou menou; odpovede vykresľujú MoneyResource z money-for-laravel — {minor, decimal, currency, exponent, formatted}, pričom minor je reťazec a formatted je len na zobrazenie. Bezplatný typ vstupenky má price: null.
  • Zoznamy sú length-aware paginátory z Laravelu (data, links, current_page, per_page, total, …) s per_page obmedzeným na events.routes.max_per_page.

Routy

Všetkých 49 rout, zoskupených, s cestami relatívne k prefixu. Riadky s poznámkou „Aj hostia“ odpovedajú aj neprihláseným; každá iná routa vyžaduje prihláseného používateľa:

Metóda · cestaNázovOprávneniePoznámky
GET /eventsevents.indexviewAnyAj hostia. Filtre objavovania nižšie → stránkovaný EventResource.
GET /events/feed.icsevents.feed—Aj hostia. ?category=&label=&organizer=alias:key&venue= → text/calendar (inline); throttle events-feeds.
GET /events/{event}events.showviewAj hostia. {data: EventResource} s hosts a viewer.can.
GET /events/{event}/calendar.icsevents.calendarviewAj hostia. text/calendar (príloha); odkaz na pripojenie len pre diváka, ktorý ho smie vidieť.
GET /events/{event}/tiersevents.tiers.indexviewAj hostia. Skryté len pre správcov.
GET /events/{event}/attendeesevents.attendees.indexviewAttendeesAj hostia. ?status=&checked_in=&tier=&per_page= (predvolene 25) — filtre len pre správcov.
GET /events/{event}/hostsevents.hosts.indexviewAj hostia. {data: [referencia spoluorganizátora]}.
GET /event-venuesevents.venues.index—Aj hostia. ?mine=1&near=lat,lng&radius=&per_page= (predvolene 25).
GET /event-venues/{venue}events.venues.show—Aj hostia.
POST /event-invitations/accept · declineevents.invitations.accept · declinetokenAj hostia. {token, response?} (predvolene going, interested) → RsvpResource (pohľad vlastníka) / {status: declined}; throttle events-rsvp.
POST /eventsevents.storecreate201 {data: EventResource}.
PATCH /events/{event} · DELETE /events/{event}events.update · destroyupdate · deleteZmenia sa len poslané polia; ?notify=0 zapíše potichu · 204.
POST /events/{event}/restoreevents.restorerestoreZmazané podujatia, len správcovia (ostatní 404).
POST /events/{event}/publish · unpublish · completeevents.publish · …publish · …{data: EventResource}
POST /events/{event}/postpone · cancelevents.postpone · cancelpostpone · cancel{reason?} (≤ 500).
POST /events/{event}/rescheduleevents.reschedulereschedule{starts_at, ends_at?, reason?}
POST /events/{event}/move-onlineevents.move-onlinemoveOnline{url, keep_venue?}
PUT · DELETE /events/{event}/posterevents.poster.update · destroyupdateMultipart poster alebo token draftu · odstráni ho.
POST /events/{event}/tiers · tiers/reorderevents.tiers.store · reordermanageTiers201 AdmissionTierResource · {order: [id typu, …]} → 204.
PATCH · DELETE /events/{event}/tiers/{tier}events.tiers.update · destroymanageTiersTyp podľa id alebo kľúča; len poslané polia · 204.
GET /events/{event}/rsvp · rsvp/qr.svgevents.rsvp.show · qr—Vaše RSVP (pohľad vlastníka) alebo null · váš kód ako image/svg+xml, Cache-Control: no-store, private.
PUT · DELETE /events/{event}/rsvpevents.rsvp.update · destroyrsvp{response, guests?, tier?, note?} · odpovie not_going; throttle events-rsvp.
POST /events/{event}/attendeesevents.attendees.storemanageAttendees{attendee: {type, id}, tier?, guests?, over_capacity?} → 201
PATCH · DELETE /events/{event}/attendees/{rsvp}events.attendees.update · destroymanageAttendees{tier?, guests?} — uplatní sa oboje alebo nič · 204.
POST · DELETE /events/{event}/attendees/{rsvp}/check-inevents.attendees.check-in · undo-check-incheckInRučný check-in {guests?} (bez kódu) · zrušenie.
POST /events/{event}/check-insevents.check-ins.storecheckInSkenovanie pri vstupe {code, guests?} → CheckInResultResource, 201 prvý raz, 200 opakovane; throttle events-check-in.
GET /events/{event}/waitlist · POST …/waitlist/promoteevents.waitlist.index · promoteviewWaitlist · manageAttendeesV poradí posúvania · {limit?} (1–1000).
POST · DELETE /events/{event}/hosts…events.hosts.store · destroymanageHosts{person: {type, id}} (Organizer) → 201 · {host} = alias:key → 204.
GET · POST · DELETE /events/{event}/invitations…events.invitations.index · store · destroyinviteTokeny sa nikdy nevykreslia · {person: {type, id}, message?} (≤ 1000) → 201 · {invitee} = alias:key → 204.
POST · PATCH · DELETE /event-venues…events.venues.store · update · destroyVenuePolicyTelo miesta konania nižšie → 201 · len poslané polia · 204.
POST /event-venues/{venue}/geocodeevents.venues.geocodeVenuePolicy geocodeVždy geokóduje znova (force).

Routa na potvrdenie platby neexistuje: potvrďte ju z webhooku poskytovateľa v PHP cez Events::rsvps()->confirmPayment($reference).

Vytvorenie podujatia

{
  "title": { "en": "Jazz Night", "sk": "Jazzový večer" },
  "venue_id": 7,
  "starts_at": "2026-11-14 20:00",
  "duration": "PT3H",
  "capacity": 120,
  "max_guests": 1,
  "category": "jazz",
  "labels": ["Live", "Late night"],
  "tiers": [
    { "name": "Free entry", "key": "free" },
    { "name": "Supporter", "price": "15.00", "currency": "EUR", "capacity": 30 }
  ],
  "publish": true
}
PolePravidlá
titlePovinné; reťazec alebo mapa jazykov, každý ≤ 200 znakov.
description≤ 20 000.
organizer{type, id} z events.organizers — predvolene volajúci; musí volajúceho povoliť.
venue_id · venueExistujúce miesto konania (akýkoľvek organizátor môže usporiadať podujatie na akomkoľvek mieste) — alebo nové miesto priamo v tele, vlastnené volajúcim: name (povinné), street, city, region, postal_code, country, coordinates, timezone.
online_url · attendance_mode · visibility · guest_list · timezone≤ 2048 · hodnoty enumov · názov IANA.
starts_at · ends_at · duration · doors_open_at · all_day_from · all_day_throughstarts_at povinné, ak nie je all_day_from; celodenné dátumy Y-m-d.
capacity · max_guests0–10,000,000 · 0–1000
waitlist · waitlist_auto_promote · show_counts · publishBoolean hodnoty; publish: true ho ohlási v tej istej transakcii.
rsvp_opens_at · rsvp_closes_at · remindersReťazce; ≤ 5 pripomienok.
category · labelsKategória stromu · ≤ 10 reťazcov (v katalógu organizátora pri events.tags.scope = organizer).
tiers≤ 50 položiek {name, key?, price?, currency?, capacity?, hidden?}; price v tvare ^\d{1,12}(\.\d{1,4})?$.
poster_draftToken draftu z media-library.

PATCH /events/{event} zmení len poslané polia a null vymaže pole, ktoré môže byť prázdne; category (null vymaže) a labels (presne tieto) sa uplatnia v tej istej transakcii. Nový začiatok ohláseného podujatia sa odmietne — použite POST /reschedule. ?notify=0, alebo notify: false v tele, zapíše potichu.

Typy vstupeniek a miesta konania

Telá typov vstupeniek prijímajú name (pri vytvorení povinné, ≤ 200), description (≤ 2000), key (≤ 64; bez neho sa odvodí z názvu), price + currency, capacity, sale_starts_at, sale_ends_at, min_party (1–1000), max_party, hidden a position. Telá miest konania prijímajú name (pri vytvorení povinné), street, city, region, postal_code, country (2 písmená), formatted_address, coordinates (lat,lng, [lat, lng] alebo {latitude, longitude}), timezone, capacity a geocode a pri vytvorení owner ({type, id}, ktorý musí volajúceho povoliť) alebo shared (len administrátori a abilities.shared_venues). Bez owner a shared patrí nové miesto volajúcemu. Pri PATCH sa každé pole adresy mení samostatne a vlastníctvo sa nikdy nemení.

Vaše RSVP

PUT /api/events/{event}/rsvp s telom:

{ "response": "going", "tier": "free", "guests": 1, "note": "Wheelchair access" }

vráti vaše vlastné RSVP v pohľade vlastníka, s kódom pre check-in a URL QR kódu:

{
  "data": {
    "id": 42,
    "status": "going",
    "guests": 1,
    "party_size": 2,
    "tier": { "id": 1, "key": "free", "name": "Free entry" },
    "note": "Wheelchair access",
    "waitlist_position": null,
    "held_until": null,
    "amount": null,
    "checked_in_at": null,
    "checked_in_guests": null,
    "responded_at": "2026-11-02T18:12:40+01:00",
    "payment_url": null,
    "check_in_code": "EV1-…",
    "qr_url": "https://example.com/api/events/0195f2c4-7a1e-7c3b-9d2e-5b8a1f4c6e21/rsvp/qr.svg"
  }
}

Zoznam hostí

GET /events/{event}/attendees vypíše správcom akýkoľvek stav (?status=, predvolene going) so záznamom o check-ine — nikdy s kódmi — a filtrom podľa checked_in a tier. Ktokoľvek iný, kto zoznam smie vidieť, uvidí len účastníkov so stavom going ako {attendee, guests}: status=interested je preňho 403 a status, checked_in a tier sa ignorujú — vždy celý zoznam, nikdy zúžený na to, kto je na mieste alebo kto má skrytý typ vstupenky.

Objavovanie: GET /events

Postavené na scopes modelu, takže PHP aj HTTP filtrujú rovnako; query-builder rozdelí každú hodnotu podľa čiarok. Základom je browse($viewer) — viditeľné, verejne uvedené, ohlásené:

ParameterScope
filter[when]=upcoming|ongoing|pastupcoming() …
filter[from], filter[to]Prekrývajúce sa s rozsahom, miestny čas v ?tz= (predvolene app.timezone).
filter[date]=2026-11-14onLocalDate() — skutočný dátum (2027-02-30 je 422).
filter[near]=48.14,17.11,25near() — polomer voliteľný, ≤ geo.max_radius_km.
filter[category]=jazzinCategory() vrátane podkategórií.
filter[labels]=live,outdoorVšetky štítky.
filter[organizer]=user:42organizedBy() — riadok sa nikdy nevyhľadáva; neexistujúci nezodpovedá ničomu.
filter[venue]=7,8 · filter[mode]=online,mixedatVenue() · withAttendanceMode()
filter[free]=true · filter[available]=truefree() · withSeatsAvailable()
filter[search]=…search() — vyhľadávanie podreťazca v názve a popise so zneškodnenými znakmi (čiarky zostanú).
filter[status]=postponed,rescheduledinPhase()
filter[mine]=organizing|attending|interestedVaše podujatia, každá viditeľnosť (organizing vrátane konceptov); hostia nedostanú nič.
sort=starts_at (default), -starts_at, created_at, -created_at, popularity, distancedistance vyžaduje filter[near] (inak 400); popularity počíta podujatie s vypnutým show_counts ako nula účastníkov — okrem filter[mine]=organizing.
per_pagePredvolene 15, ≤ events.routes.max_per_page.

Neplatná hodnota filtra je 422 invalid_query. Stránka načíta miesta konania a ich vlastníkov, organizátorov, štítky, plagáty, typy vstupeniek, vlastné RSVP diváka, cesty kategórií a to, ktoré podujatia divák spravuje, v pevnom počte dotazov — počet nerastie s veľkosťou stránky.

Resources

Bezplatné podujatie tak, ako ho vidí hosť v zozname:

{
  "id": "0195f2c4-7a1e-7c3b-9d2e-5b8a1f4c6e21",
  "slug": "jazz-night",
  "title": "Jazz Night",
  "description": "A live quartet, then an open jam session.",
  "phase": "scheduled",
  "schema_status": "EventScheduled",
  "attendance_mode": "offline",
  "starts_at": "2026-11-14T20:00:00+01:00",
  "ends_at": "2026-11-14T23:00:00+01:00",
  "doors_open_at": null,
  "previous_starts_at": null,
  "all_day": false,
  "timezone": "Europe/Bratislava",
  "starts_on": "2026-11-14",
  "ends_on": "2026-11-14",
  "venue": {
    "id": 7,
    "name": "Blue Note",
    "slug": "blue-note",
    "address": {
      "street": "Hlavná 1", "city": "Bratislava", "region": null, "postal_code": "811 01",
      "country": "SK", "formatted": "Hlavná 1, 811 01 Bratislava, SK"
    },
    "coordinates": { "latitude": 48.1439, "longitude": 17.1097 },
    "timezone": "Europe/Bratislava",
    "capacity": null,
    "owner": null,
    "distance_km": null,
    "deleted": false
  },
  "online_url": null,
  "organizer": { "id": 1, "type": "User" },
  "category": { "id": 3, "slug": "jazz", "name": "Jazz", "color": null, "icon": null, "path": ["Music"] },
  "labels": [{ "id": 4, "slug": "live", "name": "Live", "color": null, "icon": null }],
  "poster": null,
  "tiers": [
    {
      "id": 1, "key": "free", "name": "Free entry", "description": null, "price": null, "free": true,
      "capacity": null, "seats_left": null, "on_sale": true, "sale_starts_at": null, "sale_ends_at": null,
      "min_party": 1, "max_party": null, "position": 1
    }
  ],
  "capacity": 120,
  "seats_left": 85,
  "counts": { "going": 35, "waitlisted": 0 },
  "viewer": { "rsvp": null },
  "links": {
    "self": "https://example.com/api/events/0195f2c4-7a1e-7c3b-9d2e-5b8a1f4c6e21",
    "ics": "https://example.com/api/events/0195f2c4-7a1e-7c3b-9d2e-5b8a1f4c6e21/calendar.ics",
    "url": "https://example.com/en/events/jazz-night"
  }
}
ResourceTvar
EventResourcePozrite príklad vyššie. status a visibility len pre správcov; online_url pre správcov a účastníkov so stavom going; seats_left a counts pre správcov, alebo pre všetkých pri show_counts (counts.interested len pre správcov); hosts a viewer.can len v detaile.
VenueResourceid, name, slug, address {street, city, region, postal_code, country, formatted}, coordinates {latitude, longitude} | null, timezone, capacity, owner, distance_km (3 decimals, when selected), deleted — never meta
AdmissionTierResourceid, key, name, description, price (MoneyResource alebo null), free, capacity, seats_left, on_sale, sale_starts_at, sale_ends_at, min_party, max_party, position a hidden pre správcov.
RsvpResourceid, status, guests, party_size, tier {id, key, name}, note, waitlist_position, held_until, amount, checked_in_at, checked_in_guests, responded_at; pohľad vlastníka pridá payment_url (kým je rezervované), check_in_code a qr_url; pohľad správcov pridá attendee, check_in_method a checked_in_by — nikdy kód.
InvitationResourceid, status, invitee, invited_by, message, expires_at (null, kým je odložené), responded_at, sent_at — nikdy token.
CheckInResultResourcefirst_check_in, guests, checked_in_at, method, attendee, rsvp (RsvpResource)

Referenčné resources

Každá osoba či tím, ktorý odpoveď spomína, sa vykreslí cez vlastný resource — predvolene {id, type}, kde type je krátky názov triedy modelu (User), nikdy názov PHP triedy ani morph typ, aj bez morph mapy. Chýbajúci model sa vykreslí ako null:

Konfiguračný kľúčPredvolenéVykresľuje
events.resources.organizerEventOrganizerResourceorganizer
events.resources.hostEventHostResourcespoluorganizátori
events.resources.attendeeEventAttendeeResourceúčastníci
events.resources.inviteeEventInviteeResourcepozvaní
events.resources.actorEventActorResourceinvited_by, checked_in_by
events.resources.venue_ownerVenueOwnerResourcevlastník miesta konania

Ak chcete pridať meno či avatar, nastavte kľúč na vlastný JsonResource — dostane model. Prázdna hodnota znamená predvolený; čokoľvek, čo nie je inštanciovateľná podtrieda JsonResource, vyhodí výnimku s názvom kľúča. Zoznamy súvisiace modely načítajú vopred, takže resource, ktorý číta len ich atribúty, nepridá žiadne dotazy:

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

final class PersonResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return ['id' => $this->resource->getKey(), 'name' => $this->resource->name, 'avatar' => $this->resource->avatar_url];
    }
}

// config/events.php
'resources' => [
    'organizer' => App\Http\Resources\PersonResource::class,
    'host' => EventHostResource::class,
    'attendee' => App\Http\Resources\PersonResource::class,
    'invitee' => EventInviteeResource::class,
    'actor' => EventActorResource::class,
    'venue_owner' => VenueOwnerResource::class,
],

Chyby

{message, code} so stavom balíka — plus reason pri odmietnutí check-inu, denials pri zamietnutom prechode a errors pri validačnom 422. Správy sú preložené a nikdy neuvádzajú triedu a váš exception handler sa nikdy nemení:

{ "message": "This code is for another event.", "code": "check_in_refused", "reason": "wrong_event" }
StavcodeKedy
401(váš handler)Zápis bez prihláseného Eloquent používateľa.
403forbidden · invitation_requiredPolicy zamietla · súkromné podujatie bez pozvánky.
404event_not_found, venue_not_found, tier_not_found, rsvp_not_found, invalid_code, invalid_invitationNeexistuje alebo je skryté.
409event_trashed, rsvp_closed, event_full, tier_sold_out, tier_not_on_sale, hold_expired, invalid_rsvp_transition, check_in_refusedKonflikt stavu (check_in_refused pridá reason).
422validation_failed, invalid_event, invalid_schedule, invalid_venue, venue_in_use, invalid_tier, tier_key_taken, tier_in_use, tier_required, invalid_guest_count, invalid_organizer, unknown_alias, unknown_transition, transition_denied, invalid_query, tag_not_found, tag_limit_exceeded, invalid_tag, invalid_posterChybný vstup (validation_failed pridá errors, transition_denied pridá denials).
400invalid_querysort=distance bez filter[near].
429transition_denied (+ Retry-After) alebo throttlePrekročený limit požiadaviek.

Štítok iného rozsahu odpovie tag_not_found, rovnako ako chýbajúci. Plagát, ktorý media-library odmietne, alebo neznámy či vypršaný draft je invalid_poster.

Limity požiadaviek

Definujú sa, len keď sú routy zapnuté, za minútu:

LimiterPredvolenéKľúčRouty
events-apiroutes.rate_limits.api = 120používateľ, inak IPKaždá routa (v routes.middleware).
events-rsvprate_limits.rsvp = 20používateľ (alebo IP) a podujatiePUT / DELETE /rsvp, prijatie / odmietnutie pozvánky.
events-check-inrate_limits.check_in = 300používateľPOST /check-ins — skenery pri vstupe pracujú v nárazoch.
events-feedsrate_limits.feeds = 60IPfeed.ics, calendar.ics

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.