This support class allows you to easily send many of the core actions, such as messages, reactions, images, and more.
use RTippin\Messenger\Facades\MessengerComposer;
MessengerComposer::to($receiver)
->from($sender)
->emitTyping()
->message('Hello!');
- Set the
Thread
orMessengerProvider
you want to compose an actionTO
. - Set the
FROM
MessengerProvider
who is composing the action. - Decide if you want to silence the action or let it emit realtime broadcast.
- Call the action, such as
message()
to complete the cycle.- The actions instance will be returned should you need to access it.
- Set the
Thread
orMessengerProvider
you want to composeTO
. If a provider is supplied, we will attempt to locate an existing private thread between theTO
andFROM
providers. If no private thread is found, one will be created.- If the two providers are not friends, the new thread will be marked as pending for the
TO
recipient ifMESSENGER_VERIFY_PRIVATE_THREAD_FRIENDSHIP
config is enabled.
- If the two providers are not friends, the new thread will be marked as pending for the
- Set the provider who is composing. (acting as the logged-in user)
- When executing the action, no broadcast will be emitted. Optional flag
withoutEvents
disables events from dispatching in the action as well.
use App\Models\User;
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Models\Thread;
public function testing(): void
{
MessengerComposer::to(Thread::first())
->from(User::first())
->silent()
->message('I store a new message to the given thread from the provided user without broadcasting the message!');
MessengerComposer::to(User::latest()->first())
->from(User::oldest()->first())
->silent(true)
->message('I store a new message in a private thread between our two users without broadcasting or firing the new message event!');
}
- Send a message. Optional reply to message ID and extra data allowed.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Http\Resources\MessageResource;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): MessageResource
{
//Send inline directly.
MessengerComposer::to($thread)
->from($request->user())
->message('Testing hello!');
//Send and return the message actions json resource.
return MessengerComposer::to($thread)
->from($request->user())
->message($request->input('message'))
->getJsonResource();
}
- Send an image message. Optional reply to message ID and extra data allowed.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Http\Resources\MessageResource;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): MessageResource
{
//Send inline directly.
MessengerComposer::to($thread)
->from($request->user())
->image($request->file('image'));
//Send and return the message actions json resource.
return MessengerComposer::to($thread)
->from($request->user())
->image($request->file('image'))
->getJsonResource();
}
- Send a document message. Optional reply to message ID and extra data allowed.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Http\Resources\MessageResource;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): MessageResource
{
//Send inline directly.
MessengerComposer::to($thread)
->from($request->user())
->document($request->file('document'));
//Send and return the message actions json resource.
return MessengerComposer::to($thread)
->from($request->user())
->document($request->file('document'))
->getJsonResource();
}
- Send an audio message. Optional reply to message ID and extra data allowed.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Http\Resources\MessageResource;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): MessageResource
{
//Send inline directly.
MessengerComposer::to($thread)
->from($request->user())
->audio($request->file('song'));
//Send and return the message actions json resource.
return MessengerComposer::to($thread)
->from($request->user())
->audio($request->file('song'))
->getJsonResource();
}
- Send a video message. Optional reply to message ID and extra data allowed.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Http\Resources\MessageResource;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): MessageResource
{
//Send inline directly.
MessengerComposer::to($thread)
->from($request->user())
->video($request->file('video'));
//Send and return the message actions json resource.
return MessengerComposer::to($thread)
->from($request->user())
->video($request->file('video'))
->getJsonResource();
}
- Add a reaction to the supplied message.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Http\Resources\MessageReactionResource;
use RTippin\Messenger\Models\Message;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread, Message $message): MessageReactionResource
{
//Send inline directly.
MessengerComposer::to($thread)
->from($request->user())
->reaction($message, '💯');
//Send and return the message actions json resource.
return MessengerComposer::to($thread)
->from($request->user())
->reaction($message, $request->input('reaction'))
->getJsonResource();
}
- Send a knock to the given thread.
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): JsonResponse
{
MessengerComposer::to($thread)->from($request->user())->knock();
return new JsonResponse([
'message' => 'success'
]);
}
- Mark the "FROM" provider or given participant as read.
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Http\Resources\MessageReactionResource;
use RTippin\Messenger\Models\Message;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): JsonResponse
{
MessengerComposer::to($thread)->from($request->user())->read();
return new JsonResponse([
'message' => 'success'
]);
}
- Emit a typing presence client event.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): void
{
MessengerComposer::to($thread)
->from($request->user())
->emitTyping()
->message('I emit the client-event of typing to the threads presence channel!');
}
- Emit a stopped typing presence client event.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread): void
{
MessengerComposer::to($thread)
->from($request->user())
->emitTyping()
->message('I emit the client-event of typing and stopped typing to the threads presence channel!');
MessengerComposer::to($thread)->from($request->user())->emitStopTyping();
}
- Emit a read/seen presence client event. Optional message instance can be used.
use Illuminate\Http\Request;
use RTippin\Messenger\Facades\MessengerComposer;
use RTippin\Messenger\Models\Message;
use RTippin\Messenger\Models\Thread;
public function testing(Request $request, Thread $thread, Message $message): void
{
MessengerComposer::to($thread)->from($request->user())->emitRead($message);
}
- Our backend has the ability to broadcast client events (
typing
|stopped typing
|read
) that your client side can listen for, just as if the client sent the whispers themselves.
MessengerComposer::to($thread)->from($user)->emitTyping();
Thread presence channel
Echo.join('messenger.thread.1234-5678').listenForWhisper('typing', (e) => console.log(e))
Typing broadcast data
{
"provider_id" : 1234,
"provider_alias" : "user",
"name" : "John Doe",
"avatar" : "/path/to/avatar.jpg"
}
MessengerComposer::to($thread)->from($user)->emitStopTyping();
Thread presence channel
Echo.join('messenger.thread.1234-5678').listenForWhisper('stop-typing', (e) => console.log(e))
Stopped typing broadcast data
{
"provider_id" : 1234,
"provider_alias" : "user",
"name" : "John Doe",
"avatar" : "/path/to/avatar.jpg"
}
MessengerComposer::to($thread)->from($user)->emitRead($message);
Thread presence channel
Echo.join('messenger.thread.1234-5678').listenForWhisper('read', (e) => console.log(e))
Read broadcast data
{
"provider_id" : 1234,
"provider_alias" : "user",
"name" : "John Doe",
"avatar" : "/path/to/avatar.jpg",
"message_id" : "1234-5678-9999"
}
- You will need to create a simple class that extends the MessengerBroadcast class.
- Set the name for the event, usually prefixed with
client-
to emulate a client event that your frontend willlistenForWhisper
. - Once created, you will register it with the PresenceEvents support class.
- Overwriting the data only requires you to set a new closure for each client event you choose.
<?php
namespace App\Broadcasting;
use RTippin\Messenger\Broadcasting\MessengerBroadcast;
class Typing extends MessengerBroadcast
{
/**
* The event's broadcast name.
*
* @return string
*/
public function broadcastAs(): string
{
return 'client-is-typing';
}
}
class StopTyping extends MessengerBroadcast
{
/**
* The event's broadcast name.
*
* @return string
*/
public function broadcastAs(): string
{
return 'client-stopped-typing';
}
}
class Read extends MessengerBroadcast
{
/**
* The event's broadcast name.
*
* @return string
*/
public function broadcastAs(): string
{
return 'client-seen';
}
}
<?php
namespace App\Providers;
use App\Broadcasting\Read;
use App\Broadcasting\StopTyping;
use App\Broadcasting\Typing;
use Illuminate\Support\ServiceProvider;
use RTippin\Messenger\Contracts\MessengerProvider;
use RTippin\Messenger\Facades\Messenger;
use RTippin\Messenger\Models\Message;
use RTippin\Messenger\Support\PresenceEvents;
class MessengerServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//Setting the custom event classes
PresenceEvents::setTypingClass(Typing::class);
PresenceEvents::setTypingClass(StopTyping::class);
PresenceEvents::setTypingClass(Read::class);
//Setting the custom closures for data that will be broadcasted.
PresenceEvents::setTypingClosure(function (MessengerProvider $provider) {
return [
'id' => $provider->getKey(),
'name' => $provider->getProviderName(),
'typing' => true,
'extra' => 'typing',
];
});
PresenceEvents::setStopTypingClosure(function (MessengerProvider $provider) {
return [
'id' => $provider->getKey(),
'name' => $provider->getProviderName(),
'typing' => false,
'extra' => 'not typing',
];
});
PresenceEvents::setReadClosure(function (MessengerProvider $provider, ?Message $message = null) {
return [
'id' => $provider->getKey(),
'name' => $provider->getProviderName(),
'message_id' => optional($message)->id,
'extra' => 'seen',
];
});
}
}
MessengerComposer::to($thread)
->from($user)
->emitTyping()
->emitStopTyping()
->emitRead($message);
Thread presence channel
Echo.join('messenger.thread.1234-5678')
.listenForWhisper('is-typing', handleTyping)
.listenForWhisper('stopped-typing', handleStoppedTyping)
.listenForWhisper('seen', handleMessageSeen)
Typing broadcast data
{
"id" : 1234,
"name" : "John Doe",
"typing" : true,
"extra" : "typing"
}
Stopped typing broadcast data
{
"id" : 1234,
"name" : "John Doe",
"typing" : false,
"extra" : "not typing"
}
Read / seen broadcast data
{
"id" : 1234,
"name" : "John Doe",
"message_id" : "1234-5678-9999",
"extra" : "seen"
}