Building a real-time chat application with Laravel and Larasocket

Zach Vander Velden
5 min readJul 22, 2020

Nowadays, pretty much every web application requires some form of real-time communication. Laravel offers a simple interface for developers to add WebSocket technologies to their applications. For years, Pusher has been the default Laravel option. However, now there is a new option: Larasocket.

Related articles:

  1. Building a real-time chat room with Larasocket, Tailwind, Alpine, Livewire, and Laravel
  2. Larasocket: Laravel’s Newest Websocket Broadcasting Solution
  3. Laravel Broadcasting in 2020

In this article, we are going to explore Laravel’s newest broadcasting solution: Larasocket. Larasocket is a hosted, no configuration, pay as you option for handling your broadcasting in your Laravel applications.

The main benefit Larasocket offers over Pusher is pricing. When using Larasocket, you pay only for what you use, with a free tier that will get small projects off ground. You can find more details about Larasocket’s pricing here.

Getting Started

Today, we will be building a realtime chat room application. This is broken into 2 parts: the backend and the frontend. The final source code for this tutorial can be found here.

Part 1: The Backend

First, let’s get started by creating ourselves a fresh Laravel application:

laravel new larasocket-chat --auth

In order to turn on broadcasting for any Laravel application, we need to go to config/app.php and uncomment:

App\Providers\BroadcastServiceProvider::class,

Setting up Larasocket

Step 1: Include the broadcasting driver

composer require larasocket/larasocket-driver

Step 2: Add Larasocket as a broadcasting connection option in config/broadcasting.php

'larasocket' => [
'driver' => 'larasocket',
'token' => env('LARASOCKET_TOKEN'),
],

Step 3: Head on over to Larasocket.com and get yourself a free token.

Step 4: Let’s update our .env

BROADCAST_DRIVER=larasocket
LARASOCKET_TOKEN=token
MIX_LARASOCKET_TOKEN="${LARASOCKET_TOKEN}"

Our backend is now set up to start using Larasocket.

Models

Now we can create ourselves a Message model with a migration:

php artisan make:model Message -m

We can update the generatedcreate_messages_table migration to:

Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->text('message');
$table->timestamps();
});

We are done making database changes so let’s migrate our tables:

php artisan migrate

Let’s update our Message.php to look like:

class Message extends Model
{
protected $fillable = [
'message'
];

public function user() {
return $this->belongsTo(User::class);
}
}

While we are at it, let’s add a messages eloquent relationship in User.php

public function messages() {
return $this->hasMany(Message::class);
}

Controllers

Now that we have our models ready to go, we can add the endpoints needed for our chat application to send and receive messages.

php artisan make:controller MessageController

Let’s update our MessageController:

class MessageController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}

public function index()
{
return Message::with('user')->get();
}

public function store(Request $request)
{
$user = Auth::user();

$message = $user->messages()->create([
'message' => $request->input('message')
]);

return [
'message' => $message,
'user' => $user,
];
}
}

Let’s add these new routes to our web.php:

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
Route::view('/', 'chat')->middleware('auth');
Route::resource('messages', 'MessageController')->only([
'index',
'store'
]);

Broadcasting

The last thing we need to do on the backend is to set up our events so they are broadcasted when new messages are created.

php artisan make:event MessageSentEvent

This is the event that will be dispatched to our listeners. We can use it to pass real-time information to the listening clients. In this example, our clients will be a web browser. However, this could be an iOS or Android application as well.

class MessageSentEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;

public $message;
public $user;

/**
* Create a new event instance.
*
*
@return void
*/
public function __construct(Message $message, User $user)
{
$this->message = $message;
$this->user = $user;
}

/**
* Get the channels the event should broadcast on.
*
*
@return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('chat');
}
}

Important: Don’t forget to addimplements ShouldBroadcast to the class signature. Events that implement the ShouldBroadcast will be dispatched to the broadcast driver by Laravel. All public properties will be passed along as data. There is much more customization available that you can read about in the Laravel broadcasting documentation.

Back over in MessageController, we need to broadcast our new event in our store method:

public function store(Request $request)
{
$user = Auth::user();

$message = $user->messages()->create([
'message' => $request->input('message')
]);
// send event to listeners
broadcast(new MessageSentEvent($message, $user))->toOthers();

return [
'message' => $message,
'user' => $user,
];
}

Since we are only allowing authenticated users to use the chat feature, we are broadcasting events on the private chat channel. To control access to private and presence channels, Laravel uses the routes/channels.php. In that file, we will add authentication logic for the new channel.

Broadcast::channel('chat', function () {
return \Illuminate\Support\Facades\Auth::check();
});

Now it is time to build the UI.

Part 2: The Frontend

Before building the UI, let’s setup Laravel Echo to use Larasocket

npm i laravel-echo larasocket-js

Over in bootstrap.js we can now create our Echo instance using larasocket-js:

import Echo from 'laravel-echo';
import Larasocket from 'larasocket-js';
window.Echo = new Echo({
broadcaster: Larasocket,
token: process.env.MIX_LARASOCKET_TOKEN,
});

UI

Our chat application will start with a single blade view powered by VueJS. Let’s create chat.blade.view in the resources/views directory:

@extends('layouts.app')

@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<h2>Messages</h2>

<div
class="clearfix"
v-for="message in messages"
>
@{{ message.user.name }}: @{{ message.message }}
</div>

<div class="input-group">
<input
type="text"
name="message"
class="form-control"
placeholder="Type your message here..."
v-model="newMessage"
@keyup.enter="sendMessage"
>

<button
class="btn btn-primary"
@click="sendMessage"
>
Send
</button>
</div>
</div>
</div>
</div>
@endsection

The next thing we need to do is initialize VueJS. We can do that in out resources/js/app.js. Let’s replace our const app initialization with the following code:

Before:

const app = new Vue({
el: '#app',
});

After:

const app = new Vue({
el: '#app',

data: {
messages: [],
newMessage: ''
},

created() {
this.fetchMessages();

Echo.private('chat')
.listen('MessageSentEvent', (e) => {
this.messages.push({
message: e.message.message,
user: e.user
});
});
},

methods: {
fetchMessages() {
axios.get('/messages').then(response => {
this.messages = response.data;
});
},

addMessage(message) {
axios.post('/messages', {
message
}).then(response => {
this.messages.push({
message: response.data.message.message,
user: response.data.user
});
});
},

sendMessage() {
this.addMessage(this.newMessage);
this.newMessage = '';
}
}
});

Let’s compile our assets and we are ready to run this application!

npm run dev

Start our Laravel server:

php artisan serve

You can navigate to http://127.0.0.1:8000 and start playing with Larasocket.

Larasocket, in action!

If you have any questions or issues, you can get in touch here.

--

--