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

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

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ť:

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ádyAkciaexecute(…)Vracia
start()->create()StartThreadCreateThreadDataThread
direct()FindOrCreateDirectThreadModel $first, Model $secondThread
to()->send() / send()SendMessageSendMessageDataMessage
markRead() / thread()->markRead()MarkReadMarkReadDataParticipant
thread()->rename()RenameThreadThread $thread, ?string $name, ?Model $actor = nullThread
thread()->archive()ArchiveThreadThread $thread, ?Model $actor = nullThread
thread()->typing()SignalTypingThread $thread, Model $participantvoid
participants()->add()AddParticipantAddParticipantDataParticipant
participants()->remove()RemoveParticipantRemoveParticipantDatavoid
participants()->leave()LeaveThreadThread $thread, Model $participantvoid
participants()->setRole()SetParticipantRoleSetParticipantRoleDataParticipant
participants()->transferOwnership()TransferOwnershipThread $thread, Model $currentOwner, Model $newOwnerParticipant (nový vlastník)
message()->edit()EditMessageEditMessageDataMessage
message()->delete()DeleteMessageMessage $message, ?Model $actor = nullMessage
prune()PruneMessagesPruneMessagesDataint (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:

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í

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ýnimkaPomenovaný konštruktorVyhodí sa, keď
MessageExceptionalreadyDeleted()Upravujete alebo mažete správu, ktorej odoslanie už bolo zrušené, alebo na ňu odpovedáte.
MessageExceptionreplyAcrossThreads()Odpoveď cieli na správu v inom vlákne alebo na neexistujúcu správu.
MessageExceptionnotInThread()Messages::thread($t)->message($m) dostane správu z iného vlákna.
MessageExceptionattachmentIsNotAnImage()attachmentPreviewUrl() sa volá pre prílohu, ktorá nie je obrázok.
ParticipationExceptionnotAParticipant()Označenie prečítania, odobratie, zmena roly, prevod alebo signál písania pre model, ktorý vo vlákne nie je.
ParticipationExceptionownershipOnlyByTransfer()setRole() na rolu vlastníka alebo z nej, prípadne add() druhého vlastníka — pre každého volajúceho.
ParticipationExceptionownerMustTransferFirst()Vlastník odchádza alebo ho niekto odoberá, kým je vo vlákne ešte niekto iný — pre každého volajúceho.
ParticipationExceptionnotTheOwner()transferOwnership(from: …) uvádza účastníka, ktorý vlákno nevlastní.
ParticipationExceptiondirectThreadHasNoRoles()setRole() alebo transferOwnership() v priamom vlákne.
ParticipationExceptiondirectThreadIsClosed()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.
ParticipationExceptiondirectThreadTakesTwo()Priame vlákno sa zakladá s viac ako dvoma rôznymi účastníkmi.
ParticipationExceptioninAnotherThread()Metóda participants() dostane záznam Participant z iného vlákna.
ParticipationExceptionparticipantMissing()Model za záznamom Participant už neexistuje.
ParticipationExceptionthreadMissing()Participant::markAsRead() pri účasti, ktorej vlákno bolo mäkko zmazané (soft delete).
ParticipationExceptioninterfaceImplementationRequired()Broadcast payload potrebuje participateAs() z modelu bez ParticipatesInMessaging.
UnauthorizedMessagingActionrequiresRole()Vykonávateľ (actor) nie je účastníkom alebo mu chýba rola administrátora (správa vlákna), resp. vlastníka (roly, prevod).
UnauthorizedMessagingActionfor()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

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.