Broadcasting
Broadcasting is off by default — the plain events still fire either way. Turn it on to push changes live over Laravel broadcasting (Reverb, Pusher, Ably, …):
REALTIME_MESSAGES=trueWhen enabled, the Thread, Participant and Message models use Laravel’s BroadcastsEvents on create, update, delete and restore. A new thread is announced once its participants are in, so a private thread reaches every one of them.
A thread broadcasts only its creation: renaming, archiving or deleting one is not broadcast. React to the ThreadRenamed and ThreadArchived events to push those yourself — or enable system messages, which posts a (broadcast) “renamed” message into the thread.
Channels
| Channel | Type | Carries |
|---|---|---|
messaging | public | messaging.thread.created for public threads. |
messaging.participant.{name}.{id} | private | messaging.thread.created for private and direct threads — once per participant, {name} being the lowercased class basename (e.g. user) and {id} its key. |
messaging.thread.{id} | private | Participant events (joined, read, left), message events (sent, updated, unsent, restored) and typing. |
The package registers no channel authorization callbacks — authorize the private channels in your app’s routes/channels.php, for example by checking that the user is a participant of the thread (Thread::query()->forParticipant($user)).
Channel and event names
Every channel and event name is configurable:
'broadcasting' => [
'enabled' => env('REALTIME_MESSAGES', false),
'threads' => [
'public-channel' => 'messaging',
'per-participant-channel' => 'messaging.participant.{name}.{id}',
'events' => [
'created' => 'messaging.thread.created',
],
],
'participants' => [
'channel' => 'messaging.thread.{id}',
'events' => [
'created' => 'messaging.participant.joined',
'updated' => 'messaging.participant.read',
'trashed' => 'messaging.participant.left',
'restored' => 'messaging.participant.joined',
'deleted' => 'messaging.participant.left',
],
],
'typing' => [
'event' => 'messaging.participant.typing',
],
'messages' => [
'channel' => 'messaging.thread.{id}',
'events' => [
'created' => 'messaging.message.sent',
'updated' => 'messaging.message.updated',
'trashed' => 'messaging.message.unsent',
'restored' => 'messaging.message.restored',
'deleted' => 'messaging.message.unsent',
],
],
],Payloads
- Thread — id, name, is_public, everyone_can_join.
- Participant — id, participant (participateAs()), read_at, joined_at, left_at.
- Message — id, sender (participateAs()), message (null once unsent), sent_at, updated_at, deleted_at.
- Typing — thread_id, participant (participateAs()).
Typing indicators
Broadcast a live typing indicator on the thread channel — it only broadcasts (never persists), respects broadcasting.enabled, and refuses anyone who is not a current participant with a ParticipationException, whether or not broadcasting is on:
use RoundlyConsulting\Messages\Facades\Messages;
Messages::thread($thread)->typing($user); // broadcasts ParticipantTyping — never persisted
$thread->typing($user); // the same, from the modelShow your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.