---
title: "Fasáda Tickets — Tickets for Laravel | Roundly"
description: "Prehľad fasády Tickets — make() a create(), handle for($ticket), kategórie, polia, štítky, hostia, projekty, visibleTo() a sweep()."
url: https://roundly-consulting.com/sk/open-source/navody/tickets-for-laravel/fasada
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Tickets for Laravel](https://roundly-consulting.com/sk/open-source/navody/tickets-for-laravel.md)

# Fasáda Tickets

Všetko ide cez jednu fasádu, RoundlyConsulting\\Tickets\\Facades\\Tickets (globálny alias Tickets), ktorá je skratkou nad singletonom TicketsManager. Tiket od založenia po vyriešenie:

```php
use Illuminate\Support\Facades\Gate;
use RoundlyConsulting\Tickets\Facades\Tickets;

// Who is an agent is your call: is_support stands for your own agent flag. An undefined ability denies.
Gate::define('tickets.agent', fn ($user) => $user->is_support);

// A category, once: its defaults apply to every ticket filed under it.
$hardware = Tickets::categories()->make(['en' => 'Hardware', 'sk' => 'Hardvér'])
    ->defaults(priority: 'high', dueIn: 'P1D')
    ->create();

// The customer opens a ticket — numbered TCK-1, high priority, due in a day.
$ticket = Tickets::make()
    ->subject('Printer on floor 3 is jammed')
    ->description('Paper jam error E-102 since this morning.')
    ->requester($customer)
    ->category($hardware)
    ->create();

// An agent takes it, answers the customer and leaves a note only agents see.
Tickets::for($ticket)->by($agent)->claim()->start();
Tickets::for($ticket)->by($agent)->reply('A technician is on the way.', transition: 'wait');
Tickets::for($ticket)->by($agent)->note('Roller worn out, order a spare.');

// The customer's reply puts it back in the queue; the agent resolves it.
Tickets::for($ticket)->by($customer)->reply('Works again, thanks!');
Tickets::for('TCK-1')->by($agent)->resolve('Roller replaced.');

Tickets::for('TCK-1')->status();   // TicketStatus::Resolved
Tickets::for('TCK-1')->thread();   // the two public replies — never the note
```

## Metódy manažéra

| Metóda | Vracia | Čo robí |
| --- | --- | --- |
| `make()` | `TicketBuilder` | Fluentný builder pre nový tiket. |
| `create(CreateTicketData $data)` | `Ticket` | Tá istá cesta kódu ako builder. |
| `find(string $reference, bool $withTrashed = false)` | `?Ticket` | Živý tiket podľa čísla (SUP-42); s withTrashed aj soft-deleted. |
| `findOrFail(string $reference, bool $withTrashed = false)` | `Ticket` | Inak TicketNotFoundException. |
| `for(Ticket\|string $ticket)` | `TicketHandle` | Podľa modelu alebo čísla; neznáme či soft-deleted číslo vyhodí TicketNotFoundException. |
| `visibleTo(Model $user)` | `Builder<Ticket>` | Tikety, ktoré policy view povoľuje používateľovi (alebo hosťovi). |
| `project(Model&TicketProject $project)` | `ProjectTickets` | Tikety, kategórie, polia a štítky jedného projektu. |
| `categories()` | `Accessors\Categories` | Strom kategórií a ich predvolené hodnoty. |
| `fields()` | `Accessors\Fields` | Definície vlastných polí. |
| `tags()` | `Accessors\Tags` | Globálne a projektové štítky. |
| `guests()` | `Accessors\Guests` | Hostia — resolve, find, update, convert, odkazy. |
| `sweep()` | `SweepResult` | Kontrola termínov, ktorú spúšťa tickets:sweep. |
| `Tickets::fake()` | `TicketsFake` | Len na fasáde — nahrávací fake, ktorý volania aj tak vykoná (pozrite Testovanie). |

Na manažérovi je verejná aj metóda perform(), no je interná: je to jediný lievik, cez ktorý každý handle, pod-prístup, builder aj metóda modelu spúšťa svoju akciu, a háčik, cez ktorý zaznamenáva fake. Z kódu aplikácie ju nevolajte.

## Handle for($ticket)

Tickets::for($ticket) vráti nemenný TicketHandle. Mutátory vracajú handle, takže ich môžete reťaziť; metódy, ktoré niečo vytvárajú alebo čítajú, vracajú svoj výsledok. Naviazaný Ticket sa aktualizuje na mieste, takže zreťazené volanie vidí účinok predošlého:

```php
Tickets::for('SUP-42')->by($agent)->claim()->prioritize('urgent')->due(now()->addHours(4))->wait();
```

| Metóda | Vracia | Čo robí |
| --- | --- | --- |
| `by(?Model $actor) / asSystem()` | `TicketHandle` | Nový handle, ktorý nasledujúce volania pripíše aktérovi; by(null) = prihlásený používateľ, asSystem() = nikto. |
| `ticket()` | `Ticket` | Naviazaná inštancia, každé volanie ju aktualizuje na mieste (nečíta sa znova). |
| `update(UpdateTicketData $data)` | `TicketHandle` | Predmet, popis, priorita, kategória, termín, žiadateľ, meta hostiteľa — len to, čo zadáte. |
| `prioritize(BackedEnum\|string $priority)` | `TicketHandle` | Zmení prioritu. |
| `categorize(TicketCategory\|int\|null $category)` | `TicketHandle` | Predvolené hodnoty kategórie sa znova neuplatnia; novo povinné polia potrebujú hodnotu. |
| `due(?CarbonInterface $at)` | `TicketHandle` | Nastaví, posunie alebo zruší termín; posun znova aktivuje príznaky po termíne a tesne pred termínom. |
| `changeRequester(Model\|GuestData $requester)` | `TicketHandle` | Automatické sledovanie predošlého žiadateľa zanikne; odkazy predošlého žiadateľa-hosťa sa zneplatnia. |
| `assign(Model $assignee) / unassign() / claim()` | `TicketHandle` | Priradenie — pozrite Priradenie a sledujúci. |
| `transition(string $name, ?string $reason = null, array $payload = [])` | `TransitionResult` | Ľubovoľný prechod nakonfigurovaného životného cyklu (výsledok z lifecycle). |
| `start(), wait(), hold($reason), resume(), resolve($resolution), reopen($reason), close($reason), dismiss($reason)` | `TicketHandle` | Prechody dodaného životného cyklu. |
| `can(string $transition)` | `bool` | Či je prechod práve teraz povolený pre tohto aktéra. |
| `allowedTransitions()` | `list<string>` | Všetky práve povolené prechody. |
| `status()` | `TicketState` | Aktuálny stav. |
| `reply(string $body, ?string $transition = null, array $attachments = [], ?string $channel = null, ?string $reason = null, array $payload = [], array $meta = [])` | `Comment` | Verejná odpoveď; prechod sa uplatní atomicky — a len ak sa odpoveď zverejní. Prílohy sú uploady alebo lokálne cesty. |
| `note(string $body, array $attachments = [], ?string $channel = null, array $meta = [])` | `Comment` | Interná poznámka — len agenti pre tento tiket a systém. |
| `editComment(Comment $comment, string $body)` | `Comment` | Zaznamená sa ako comment\_edited; komentár iného tiketu vyhodí TicketCommentNotFoundException. |
| `deleteComment(Comment $comment)` | `TicketHandle` | Zaznamená sa ako comment\_deleted. |
| `thread(bool $internal = false)` | `Collection<int, Comment>` | Od najstaršej; len verejné, alebo všetky správy. |
| `activity(bool $internal = false)` | `Collection<int, TicketActivity>` | Od najstaršieho; len verejné záznamy, alebo všetky — rovnako bezpečné predvolenie ako thread(). |
| `fields() / tags() / watchers() / links() / attachments()` | `TicketFields / TicketTags / …` | Pod-prístupy — nižšie. |
| `mergeInto(Ticket\|string $target, ?string $reason = null)` | `MergeResult` | Zlúči tento tiket do cieľového (pozrite Zlučovanie tiketov). |
| `guestLink(?Model $guest = null)` | `string` | Pre žiadateľa-hosťa alebo hosťa medzi sledujúcimi, kým je zapnuté watchers.can\_view; pre kohokoľvek iného vyhodí GuestAccessDeniedException. |
| `revokeGuestAccess()` | `TicketHandle` | Zneplatní všetky doteraz vydané odkazy. |
| `delete() / restore()` | `TicketHandle` | Soft delete / obnovenie. |

## Pod-prístupy

| Prístup | Metódy |
| --- | --- |
| `fields() → TicketFields` | `set($key, $value), setMany(array), forget(array\|string), get($key), all(), definitions(), ticket()` |
| `tags() → TicketTags` | `attach($tags), detach($tags), sync(array), all(), ticket()` |
| `watchers() → TicketWatchers` | `add($model), remove($model), watch(), unwatch(), has($model), all(), ticket()` |
| `links() → TicketLinks` | `add($other, LinkType), remove($other, LinkType), all(): list<TicketLinkView>, ticket()` |
| `attachments() → TicketAttachments` | `add($file): Media, remove(Media\|string $media), all(), ticket()` |

Mutátory pod-prístupov vracajú samotný pod-prístup, takže sa reťazia v rámci svojej oblasti: ->tags()->attach(\['vip'\])->detach(\['spam'\]). Každá zmena soft-deleted tiketu vyhodí TicketTrashedException (lifecycle jeho prechody odmietne cez SubjectTrashedException).

Rozsah je bezpečnostná hranica. Handle odmietne všetko, čo nepatrí jeho tiketu: komentár iného tiketu, prepojenie, ktorého tento tiket nie je súčasťou, médium iného vlastníka či odkaz pre hosťa pre niekoho, kto nie je žiadateľom-hosťom ani hosťom medzi sledujúcimi. ProjectTickets::for() odmietne tiket iného projektu.

## Tickets::categories()

| Metóda | Vracia | Čo robí |
| --- | --- | --- |
| `make(array\|string $name)` | `CategoryBuilder` | description(), project(), under(), position(), active(), inactive(), defaults(priority:, assignee:, dueIn:), data(), create(). |
| `create(CategoryData $data)` | `TicketCategory` | DTO podoba buildera. |
| `update(TicketCategory $category, UpdateCategoryData $data)` | `TicketCategory` | Len zadané polia; bez rodiča (použite move()) a bez projektu (je pevný). |
| `move(TicketCategory $category, TicketCategory\|int\|null $parent, ?int $position = null)` | `TicketCategory` | Rodič null ju presunie do koreňa. |
| `delete(TicketCategory $category, TicketCategory\|int\|null $reassignTo = null)` | `TicketCategory` | Soft delete; reassignTo je potrebné, kým ju používajú živé tikety. |
| `restore(TicketCategory $category)` | `TicketCategory` | Obnoví ju v pôvodnej podobe. |
| `find(int $id)` | `?TicketCategory` | Podľa id. |
| `tree(?Model $project = null)` | `Collection` | Korene s načítanými potomkami — globálny strom plus strom projektu. |

Názov ako reťazec je v aktuálnom jazyku; pole je mapa jazykov (\['en' => 'Hardware', 'sk' => 'Hardvér'\]).

## Tickets::fields()

| Metóda | Vracia | Čo robí |
| --- | --- | --- |
| `make(string $key, FieldType $type)` | `FieldBuilder` | label(), help(), options(), rules(), required(), encrypted(), default(), requesterVisible(), requesterEditable(), agentOnly(), position(), active(), inactive(), project(), category(), data(), define(). |
| `define(FieldData $data)` | `TicketField` | DTO podoba buildera. |
| `update(TicketField $field, UpdateFieldData $data)` | `TicketField` | Len zadané atribúty. |
| `delete(TicketField $field) / restore(TicketField $field)` | `TicketField` | Soft delete hodnoty skryje; obnovenie ich vráti. |
| `prune(bool $dryRun = false, int $chunk = 200)` | `int` | Počet zabudnutých (alebo spočítaných) osirotených hodnôt. |
| `find(int\|string $idOrKey, ?Model $project = null)` | `?TicketField` | Živé pole podľa id alebo kľúča: s projektom jeho pole alebo globálne; bez projektu globálne. |
| `for(Ticket\|TicketCategory $subject, ?Model $project = null)` | `array<string, FieldDefinition>` | Platná sada polí podľa kľúča, v poradí. |

## Tickets::tags()

| Metóda | Vracia | Čo robí |
| --- | --- | --- |
| `create(TagData\|string $name, ?string $color = null, ?Model $project = null)` | `TicketTag` | Vytvorí štítok (opätovné vytvorenie zmazaného názvu ho obnoví, bez tiketov). |
| `findOrCreate(string $name, ?Model $project = null)` | `TicketTag` | Súbežné volania vytvoria jediný štítok. |
| `rename(TicketTag $tag, string $name) / recolor(TicketTag $tag, ?string $color)` | `TicketTag` | Slug nasleduje premenovanie. |
| `update(TicketTag $tag, UpdateTagData $data)` | `TicketTag` | Názov a farba. |
| `delete(TicketTag $tag)` | `TicketTag` | Vráti zmazaný štítok a odoberie ho zo všetkých tiketov. |
| `find(int\|string $idOrSlug, ?Model $project = null)` | `?TicketTag` | Živý štítok podľa id alebo slugu (názov sa prevedie na slug): projektový, inak globálny. |
| `all(?Model $project = null)` | `Collection` | Globálne štítky plus štítky projektu, podľa názvu. |

## Tickets::guests()

| Metóda | Vracia | Čo robí |
| --- | --- | --- |
| `resolve(GuestData\|array $fields)` | `TicketGuest` | Nájde alebo vytvorí hosťa z jeho polí — zvalidovaných a normalizovaných. |
| `find(GuestData\|array $fields)` | `?TicketGuest` | Zhoda len na čítanie podľa normalizovanej identifikačnej hodnoty — nikdy nič nevytvorí, nedoplní ani nezvaliduje; fake ju nezaznamená. |
| `update(TicketGuest $guest, GuestData\|array $fields)` | `TicketGuest` | Zmení polia hosťa. |
| `convert(TicketGuest $guest, Model $user)` | `int` | Presunie všetky tikety a sledovania na registrovaného používateľa; vráti počet presunutých tiketov. |
| `linkFor(Ticket\|string $ticket, ?TicketGuest $guest = null)` | `string` | To isté ako Tickets::for($ticket)->guestLink(). |

## Tickets::project($project)

| Metóda | Vracia | Čo robí |
| --- | --- | --- |
| `project()` | `Model&TicketProject` | Projekt. |
| `make()` | `TicketBuilder` | Builder už nastavený na projekt. |
| `tickets()` | `Builder` | Tikety projektu ako dopyt. |
| `find(string $reference)` | `?Ticket` | Tiket tohto projektu. |
| `for(Ticket\|string $ticket)` | `TicketHandle` | Tiket iného projektu vyhodí výnimku. |
| `categories() / tags()` | `Collection` | Globálne plus projektové. |
| `fields(TicketCategory\|int\|null $category = null)` | `array` | Sada polí, ktorú dostane tiket tohto projektu (a kategórie). |

## Traity modelov

Traity delegujú na manažéra, takže všetko, čo robia, zaznamená aj fake:

| Trait | Pre | Pridáva |
| --- | --- | --- |
| `Concerns\RequestsTickets` | používateľ vašej aplikácie | `requestedTickets(), assignedTickets(), watchedTickets(), visibleTickets(), openTicket(): TicketBuilder` |
| `Concerns\HasTickets` | projekt vašej aplikácie (implementuje TicketProject) | `tickets(), ticketCategories(), ticketFields(), ticketTags(), ticketing(): ProjectTickets, openTicket()` |
| `Concerns\IsTicketAssignee` | akýkoľvek riešiteľ | `ticketAssigneeName(), ticketNotifiables(), isEligibleTicketAssignee(Ticket)` |
| `Concerns\HasConfigurableKey` | Ticket a TicketGuest z balíka (na podtriede ho ponechajte) | `configuredKeyType(): KeyType, newUniqueId()` |

## Dátové objekty

Každé DTO je final readonly:

| DTO | Polia |
| --- | --- |
| `CreateTicketData` | subject, requester (Model\|GuestData), ?description, ?category, ?priority, ?project, ?assignee, ?dueAt, ?channel, ?actor, system, fields, tags, watchers, attachments (uploady alebo lokálne cesty), meta (patrí hostiteľovi). |
| `UpdateTicketData` | subject, description, priority, category, dueAt, requester, meta (nahradí celú mapu; \[\] ju vyprázdni) — každé predvolene Support\\Optional (nezadané), takže null môže hodnotu zrušiť. |
| `GuestData` | fields: array<string, scalar\|null>. |
| `CategoryData / UpdateCategoryData` | name, ?description, ?parent, ?project, position, active, ?defaultPriority, ?defaultAssignee, ?defaultDueIn (CarbonInterval\|string). Pri úprave je každé pole Optional, bez parent a project. |
| `FieldData / UpdateFieldData` | key, type, label, ?help, options, rules, required, encrypted, default, requesterVisible, requesterEditable, position, active, ?project, ?category. Pri úprave je každé Optional — key, project a category sú pevné. |
| `TagData / UpdateTagData` | name, ?color, ?project / name, color (Optional). |
| `TransitionData, ReplyData` | transition, ?reason, payload / body, attachments, ?channel, meta. |
| `MergeResult` | source, target, comments (presunuté), attachments (presunuté). |
| `TicketLinkView` | link (id), ticket (druhý koniec), type, label, direction (outgoing / incoming). |
| `SweepResult` | overdue, dueSoon — tikety, ktoré táto kontrola novo označila; total(): int ich sčíta. |
| `FieldDefinition` | Vyhodnotené pole: id, key, type, label (mapa jazykov), options, rules, required, encrypted, default, requesterVisible, requesterEditable, categoryId; label(?string $locale), attributeDefinition(), validationRules(string $prefix). |

## PHP API dôveruje volajúcemu

Fasáda vynucuje doménové pravidlá — žiadateľ nesmie pridať poznámku, priradiť možno len vhodného riešiteľa, uzavretý tiket neprijme správu, zlučovanie vyžaduje oprávnenie merge, rozsah agentov rozhoduje, kto je pre tiket agentom —, nikdy sa však nepýta TicketPolicy. Policy je autoritou HTTP API; aplikácia, ktorá volá fasádu, rozhoduje, kto smie čo volať.

## 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](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

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

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/tickets-for-laravel.md)
