Laravel 11 was released a few weeks ago and with it is laravel reverb, a first-party websocket package to help with real-time applications.
In this article I'll demonstrate how to make a simple chatbox component for support-related purposes...
first off we'll create a new laravel application using laravel new
laravel new chatbox
cd chatbox
then after all installation is complete we can use the new command to install laravel reverb
php artisan install:broadcasting
make sure the .env file has this line set to sync
QUEUE_CONNECTION=sync
next all we have to do is to create an event and listen on its channel
php artisan make:event MessageSent
and make it look something like this
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*/
public function __construct( public string $name, public string $text)
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new Channel('messages'),
];
}
}
next we create the livewire component to listen on the channel
php artisan make:volt ChatBox --class
and make it like so...
<?php
use App\Events\MessageSent;
use Livewire\Volt\Component;
new class extends Component
{
/**
* @var string[]
*/
public array $messages = [];
public string $message = '';
protected $listeners = ['echo:messages,MessageSent' => 'onMessageSent'];
public function addMessage()
{
MessageSent::dispatch(auth()->user()->name, $this->message);
$this->reset('message');
}
#[On('echo:messages,MessageSent')]
public function onMessageSent($event)
{
$this->messages[] = $event;
}
}
?>
<div x-data="{ open: true }" >
<div :class="{'-translate-y-0': open, 'translate-y-full': !open}" class="fixed transition-all duration-300 transform bottom-10 right-12 h-60 w-80">
<div class="mb-2">
<button @click="open = !open" type="button" :class="{ 'text-indigo-600 dark:text-white hover:bg-transparent': open }" class="w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 text-sm text-white rounded-lg hover:bg-indigo-400 dark:bg-indigo-600 dark:hover:bg-indigo-400">
Chat
<x-heroicon-o-chevron-up x-show="!open" x-cloak class="ms-auto block size-4" />
<x-heroicon-o-chevron-down x-show="open" x-cloak class="ms-auto block size-4" />
</button>
</div>
<div class="w-full h-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded overflow-auto flex flex-col px-2 py-4">
<div x-ref="chatBox" class="flex-1 p-4 text-sm flex flex-col gap-y-1">
@foreach($messages as $message)
<div><span class="text-indigo-600">{{ $message['name'] }}:</span> <span class="dark:text-white">{{ $message['text'] }}</span></div>
@endforeach
</div>
<div>
<form wire:submit.prevent="addMessage" class="flex gap-2">
<x-text-input wire:model="message" x-ref="messageInput" name="message" id="message" class="block w-full" />
<x-primary-button>
Send
</x-primary-button>
</form>
</div>
</div>
</div>
</div>
next we add it anywhere to the welcome page of the default laravel, and we need to start the reverb server...
php artisan serve
and on another terminal
php artisan reverb:start
and we are all set!
the chatbox should be working and all should be complete
Top comments (1)
I would have loved it to be that easy, but i ran into some difficulties.
I'm using ddev for my project, instead of running it on my OS. So some of the problems could be caused by this setup.
I'm not a laravel expert so some of the things are due to my lack of knowledge.
The first thing I encountered was the creation of the livewire component. I started from a fresh laravel 11 installation so i needed to add livewire and volt.
For people, like me, who are not that familiar with livewire. The way to add the volt component is;
The next thing I got an error on was x-heroicon-o-chevron-up in the volt component.
After a quick search I found it came from github.com/blade-ui-kit/blade-hero.... So I added that.
The next things where x-text-input and x-primary-button. To get it running as fast as possible I just converted them to plain html tags
Now I could see the page without errors, and the component was visible. When I added some text and clicked the send button, I got an error on the
MessageSent::dispatch(auth()->user()->name, $this->message);
line of the volt component. So i replaced getting the user name with a static string.update:
Adding the following to .ddev/config.yaml exposed the port
My ddev app is also named reverb so I don't need other urls.
After sending a message I couldn't see a change. In the browser console I got the error log; couldn't find Echo.
The fix was to add
@vite('resources/js/app.js')
to the page template.I didn't look for the reason that
wsHost: import.meta.env.VITE_REVERB_HOST
in resources/js/echo.js translated to localhost during the build, so I changed it to reverb.ddev.site.Now I can send a message and see it. But when I want to send a second message I get an internal server error: Pusher error: Internal server error.. {"exception":"[object]
So it almost works, but now I hit a wall because the error log is not helpful.