---
title: "DI, akcie, DTO a výnimky — Messages for Laravel | Roundly"
description: "Vložte si MessagesManager alebo spúšťajte akcie sami — mapa fasáda → akcia, DTO, ktoré akcie prijímajú, a typované výnimky, ktoré vyhadzujú."
url: https://roundly-consulting.com/sk/open-source/navody/messages-for-laravel/akcie-a-dto
language: sk
---

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

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

# DI, akcie, DTO a výnimky

Fasáda je odporúčaná voľba, nie jediná cesta. K dispozícii sú tri rovnocenné vstupy a všetky spúšťajú ten istý kód:

- Fasáda Messages — najkratšie volania, aké používa celá táto dokumentácia.
- Manager RoundlyConsulting\\Messages\\MessagesManager — koreň fasády, registrovaný ako singleton. Vložte si ho cez konštruktor a získate to isté API ako explicitnú závislosť, bez statických volaní.
- Akcie v RoundlyConsulting\\Messages\\Actions — jednoúčelové triedy s metódou execute(…), ktoré skladáte do vlastných akcií, jobov a príkazov.

## Vloženie managera

```php
use RoundlyConsulting\Messages\MessagesManager;

final class ThreadController
{
    public function __construct(private MessagesManager $messages) {}

    public function rename(Thread $thread, Request $request): Thread
    {
        return $this->messages->thread($thread)->rename($request->name, by: $request->user());
    }
}
```

Messages::fake() podstrčí podtyp MessagesManager, takže fake dostanú aj managery vložené cez konštruktor.

## Spustenie akcie

Každú akciu získate z kontajnera, prijíma DTO alebo bežné argumenty a spustí svoju udalosť:

```php
use RoundlyConsulting\Messages\Actions\EditMessage;
use RoundlyConsulting\Messages\DataTransferObjects\EditMessageData;

app(EditMessage::class)->execute(new EditMessageData($message, 'fixed typo', actor: $alice));
```

Priamo volané akcie Messages::fake() obchádzajú; fasáda, manager aj traity modelov idú cez neho.

## Metóda fasády → akcia

| Metóda fasády | Akcia | execute(…) | Vracia |
| --- | --- | --- | --- |
| `start()->create()` | `StartThread` | CreateThreadData | Thread |
| `direct()` | `FindOrCreateDirectThread` | Model $first, Model $second | Thread |
| `to()->send() / send()` | `SendMessage` | SendMessageData | Message |
| `markRead() / thread()->markRead()` | `MarkRead` | MarkReadData | Participant |
| `thread()->rename()` | `RenameThread` | Thread $thread, ?string $name, ?Model $actor = null | Thread |
| `thread()->archive()` | `ArchiveThread` | Thread $thread, ?Model $actor = null | Thread |
| `thread()->typing()` | `SignalTyping` | Thread $thread, Model $participant | void |
| `participants()->add()` | `AddParticipant` | AddParticipantData | Participant |
| `participants()->remove()` | `RemoveParticipant` | RemoveParticipantData | void |
| `participants()->leave()` | `LeaveThread` | Thread $thread, Model $participant | void |
| `participants()->setRole()` | `SetParticipantRole` | SetParticipantRoleData | Participant |
| `participants()->transferOwnership()` | `TransferOwnership` | Thread $thread, Model $currentOwner, Model $newOwner | Participant (nový vlastník) |
| `message()->edit()` | `EditMessage` | EditMessageData | Message |
| `message()->delete()` | `DeleteMessage` | Message $message, ?Model $actor = null | Message |
| `prune()` | `PruneMessages` | PruneMessagesData | int (počet zmazaných správ) |

unreadCount(), inboxFor(), threads() a thread()->messages() len čítajú, preto žiadnu akciu nemajú.

## DTO

Readonly DTO v RoundlyConsulting\\Messages\\DataTransferObjects:

```php
new CreateThreadData(?string $name = null, ?bool $isPublic = null, ?bool $everyoneCanJoin = null, bool $isDirect = false, array $participants = [], ?string $directKey = null);
// $directKey null: StartThread keys a direct thread of 1–2 distinct participants itself (more than 2 throws directThreadTakesTwo()).
new SendMessageData(Thread $thread, ?Model $sender, string $body, MessageType $type = MessageType::Text, array $meta = [], int|string|null $parentMessageId = null, array $attachments = [], array $uploads = [], bool $requireParticipation = true);
new EditMessageData(Message $message, string $body, ?Model $actor = null); // actor must be the author
new MarkReadData(Thread $thread, Model $participant);
new AddParticipantData(Thread $thread, Model $participant, ?ParticipantRole $role = null, ?Model $actor = null, bool $creatingThread = false);
// $creatingThread: internal — set only by StartThread while it seats a new thread's participants.
new RemoveParticipantData(Thread $thread, Model $participant, ?Model $actor = null);
new SetParticipantRoleData(Thread $thread, Model $participant, ParticipantRole $role, ?Model $actor = null);
new PruneMessagesData(int $days, int|string|null $threadId = null); // $days < 1 → InvalidArgumentException
```

## Skladanie akcií

```php
use RoundlyConsulting\Messages\Actions\SendMessage;
use RoundlyConsulting\Messages\Actions\StartThread;
use RoundlyConsulting\Messages\DataTransferObjects\CreateThreadData;
use RoundlyConsulting\Messages\DataTransferObjects\SendMessageData;

$thread = app(StartThread::class)->execute(new CreateThreadData(
    name: 'Support',
    isPublic: false,
    participants: [$customer, $agent],   // the first participant becomes the owner
));

app(SendMessage::class)->execute(new SendMessageData(
    thread: $thread,
    sender: $customer,
    body: 'My order has not arrived yet.',
    meta: ['order' => 'A-1042'],
));
```

SendMessage odmietne odosielateľa, ktorý nie je aktuálnym účastníkom, pokiaľ requireParticipation nie je false (to nastaví withoutParticipationCheck()), vytvorí správu a naviaže jej prílohy v jednej transakcii, aktualizuje last\_activity\_at vlákna a MessageSent spustí až po commite. Odoslania do jedného vlákna idú postupne: SendMessage pred vložením správy zamkne riadok vlákna a vlákno, ktoré ste odovzdali, potom drží ukazovateľ poslednej správy, ktorý balík uložil — nie nevyhnutne práve odoslanú správu.

## Výnimky

Všetky sú v RoundlyConsulting\\Messages\\Exceptions; ich texty sa zostavujú v aktuálnom jazyku z reťazcov messages-translations (balík obsahuje angličtinu a slovenčinu):

| Výnimka | Pomenovaný konštruktor | Vyhodí sa, keď |
| --- | --- | --- |
| `MessageException` | alreadyDeleted() | Upravujete alebo mažete správu, ktorej odoslanie už bolo zrušené, alebo na ňu odpovedáte. |
| `MessageException` | replyAcrossThreads() | Odpoveď cieli na správu v inom vlákne alebo na neexistujúcu správu. |
| `MessageException` | notInThread() | Messages::thread($t)->message($m) dostane správu z iného vlákna. |
| `MessageException` | attachmentIsNotAnImage() | attachmentPreviewUrl() sa volá pre prílohu, ktorá nie je obrázok. |
| `ParticipationException` | notAParticipant() | Označenie prečítania, odobratie, zmena roly, prevod alebo signál písania pre model, ktorý vo vlákne nie je. |
| `ParticipationException` | ownershipOnlyByTransfer() | setRole() na rolu vlastníka alebo z nej, prípadne add() druhého vlastníka — pre každého volajúceho. |
| `ParticipationException` | ownerMustTransferFirst() | Vlastník odchádza alebo ho niekto odoberá, kým je vo vlákne ešte niekto iný — pre každého volajúceho. |
| `ParticipationException` | notTheOwner() | transferOwnership(from: …) uvádza účastníka, ktorý vlákno nevlastní. |
| `ParticipationException` | directThreadHasNoRoles() | setRole() alebo transferOwnership() v priamom vlákne. |
| `ParticipationException` | directThreadIsClosed() | participants()->add() v už existujúcom priamom vlákne — pre každého volajúceho vrátane dôveryhodných a aj pre toho, kto vlákno opustil. |
| `ParticipationException` | directThreadTakesTwo() | Priame vlákno sa zakladá s viac ako dvoma rôznymi účastníkmi. |
| `ParticipationException` | inAnotherThread() | Metóda participants() dostane záznam Participant z iného vlákna. |
| `ParticipationException` | participantMissing() | Model za záznamom Participant už neexistuje. |
| `ParticipationException` | threadMissing() | Participant::markAsRead() pri účasti, ktorej vlákno bolo mäkko zmazané (soft delete). |
| `ParticipationException` | interfaceImplementationRequired() | Broadcast payload potrebuje participateAs() z modelu bez ParticipatesInMessaging. |
| `UnauthorizedMessagingAction` | requiresRole() | Vykonávateľ (actor) nie je účastníkom alebo mu chýba rola administrátora (správa vlákna), resp. vlastníka (roly, prevod). |
| `UnauthorizedMessagingAction` | for() | Odosielateľ nie je aktuálnym účastníkom alebo vykonávateľ (actor) nesmie túto správu zmazať či upraviť, odobrať účastníka s rovnakou alebo vyššou rolou, prípadne sa sám pridať do vlákna, ktoré nie je otvorené pre všetkých. |

Messages::prune() a akcia PruneMessages navyše vyhodia InvalidArgumentException z PHP pri období uchovávania kratšom ako 1 deň — skôr, než sa čokoľvek zmaže.

## 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/messages-for-laravel.md)
