How to Build a Chat Application with Laravel Echo and Pusher
In this tutorial, we will learn how to build a real-time chat application using Laravel Echo and Pusher. Laravel Echo is a JavaScript library that makes it easy to handle real-time events in Laravel applications. Pusher is a hosted service that allows us to send and receive real-time messages.
By the end of this tutorial, you will have a fully functional chat application where users can send and receive messages in real-time.
Prerequisites
To follow along with this tutorial, you will need the following:
- Basic knowledge of Laravel framework
- PHP installed on your system
- Composer installed on your system
- Node.js installed on your system
- Laravel project setup with database configuration
Step 1: Setup Laravel Project
First, let’s setup a new Laravel project by running the following command in your terminal:
composer create-project --prefer-dist laravel/laravel chatapp
This will create a new Laravel project named chatapp
. Once the project is created, navigate to the project directory:
cd chatapp
Step 2: Install Laravel Echo
To install Laravel Echo, we need to install the laravel-echo
package via npm:
npm install --save laravel-echo pusher-js
This will install the required packages for Laravel Echo and Pusher. Next, we need to configure Laravel Echo to work with our application.
Step 3: Configure Laravel Echo
Open the bootstrap.js
file located in the resources/js
directory and add the following lines of code at the top of the file:
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true
});
This will configure Laravel Echo with the required settings. Next, open the .env
file located in the root directory of your Laravel project and add the following lines of code:
PUSHER_APP_ID=your_app_id
PUSHER_APP_KEY=your_app_key
PUSHER_APP_SECRET=your_app_secret
PUSHER_APP_CLUSTER=your_app_cluster
Replace your_app_id
, your_app_key
, your_app_secret
, and your_app_cluster
with your actual Pusher credentials. Save the file once done.
Step 4: Create Chatroom Model and Migration
Next, let’s create a Chatroom
model and a migration to store the chatroom details. Run the following command in your terminal:
php artisan make:model Chatroom -m
This will create a new Chatroom
model and a migration file. Open the newly created migration file located in the database/migrations
directory and update the up
method as follows:
public function up()
{
Schema::create('chatrooms', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
This will create an id
, name
, and timestamps
columns in the chatrooms
table. Save the file once done.
Step 5: Create User Model and Migration
Next, let’s create a User
model and a migration file to store user details. Run the following command in your terminal:
php artisan make:model User -m
This will create a new User
model and a migration file. Open the newly created migration file located in the database/migrations
directory and update the up
method as follows:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
This will create the required columns in the users
table. Save the file once done.
Step 6: Create Chat Messages Model and Migration
Next, let’s create a ChatMessage
model and a migration file to store chat messages. Run the following command in your terminal:
php artisan make:model ChatMessage -m
This will create a new ChatMessage
model and a migration file. Open the newly created migration file located in the database/migrations
directory and update the up
method as follows:
public function up()
{
Schema::create('chat_messages', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('chatroom_id');
$table->unsignedBigInteger('user_id');
$table->text('message');
$table->timestamps();
});
}
This will create the required columns in the chat_messages
table. Save the file once done.
Step 7: Run Migrations
Next, let’s run the migrations to create the required tables in the database. Run the following command in your terminal:
php artisan migrate
This will create the chatrooms
, users
, and chat_messages
tables in your database.
Step 8: Create Routes
Now, let’s create some routes to handle the chat application functionality. Open the routes/web.php
file located in the root directory of your Laravel project and update the file as follows:
use AppHttpControllersChatController;
Route::get('/', [ChatController::class, 'index'])->name('chat.index');
Route::post('/message', [ChatController::class, 'sendMessage'])->name('chat.sendMessage');
Route::get('/messages', [ChatController::class, 'getMessages'])->name('chat.getMessages');
This will define three routes for the chat application: /
to display the chat interface, /message
to send a message, and /messages
to fetch the chat messages.
Step 9: Create Chat Controller
Next, let’s create a ChatController
to handle the chat application functionality. Run the following command in your terminal:
php artisan make:controller ChatController
This will create a new ChatController
in the app/Http/Controllers
directory. Open the newly created ChatController
file and update the file as follows:
namespace AppHttpControllers;
use AppModelsChatMessage;
use AppModelsChatroom;
use IlluminateHttpRequest;
class ChatController extends Controller
{
public function index()
{
$chatrooms = Chatroom::all();
return view('chat.index', compact('chatrooms'));
}
public function sendMessage(Request $request)
{
$user = auth()->user();
$message = $user->messages()->create([
'chatroom_id' => $request->input('chatroom_id'),
'message' => $request->input('message')
]);
return response()->json($message);
}
public function getMessages()
{
$messages = ChatMessage::with('user')->latest()->limit(50)->get();
return response()->json($messages);
}
}
This will define three methods in the ChatController
. The index
method returns the chat view, the sendMessage
method saves a new chat message to the database, and the getMessages
method returns the 50 latest chat messages.
Step 10: Create Chat Index View
Next, let’s create a chat index view. Run the following command in your terminal:
mkdir resources/views/chat
touch resources/views/chat/index.blade.php
This will create a new directory chat
in the resources/views
directory and a new index.blade.php
file inside it. Open the index.blade.php
file and update the file as follows:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-3">
<h3>Chatrooms</h3>
<ul>
@foreach($chatrooms as $chatroom)
<li>{{ $chatroom->name }}</li>
@endforeach
</ul>
</div>
<div class="col-md-9">
<h3>Chat</h3>
<div id="chat-messages"></div>
<form>
<div class="form-group">
<input type="text" id="message-input" class="form-control" placeholder="Message">
</div>
<button type="submit" id="send-message" class="btn btn-primary">Send</button>
</form>
</div>
</div>
</div>
@endsection
@section('scripts')
<script>
var chatroomId = null;
// Fetch chat messages
function fetchMessages() {
axios.get('/messages')
.then(function (response) {
var chatMessages = '';
response.data.forEach(function (message) {
chatMessages += '<p><strong>' + message.user.name + '</strong>: ' + message.message + '</p>';
});
document.getElementById('chat-messages').innerHTML = chatMessages;
})
.catch(function (error) {
console.log(error);
});
}
// Send chat message
function sendMessage(event) {
event.preventDefault();
var message = document.getElementById('message-input').value;
if (chatroomId && message) {
axios.post('/message', { chatroom_id: chatroomId, message: message })
.then(function (response) {
// Clear input field
document.getElementById('message-input').value = '';
// Fetch messages again
fetchMessages();
})
.catch(function (error) {
console.log(error);
});
}
}
// Event Listeners
document.getElementById('send-message').addEventListener('click', sendMessage);
// Fetch messages on page load
window.addEventListener('DOMContentLoaded', function () {
fetchMessages();
});
</script>
@endsection
This will create the chat index view with a list of chatrooms, a chat window, and a form to send messages. The JavaScript code handles fetching and displaying chat messages, sending messages, and updating the chat window in real-time.
Step 11: Update Layout
Open the resources/views/layouts/app.blade.php
file and update the file as follows:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ config('app.name', 'Laravel') }}</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
{{ config('app.name', 'Laravel') }}
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav mr-auto">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Authentication Links -->
@guest
@if (Route::has('login'))
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
</li>
@endif
@if (Route::has('register'))
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
</li>
@endif
@else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ Auth::user()->name }}
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
@csrf
</form>
</div>
</li>
@endguest
</ul>
</div>
</div>
</nav>
<main class="py-4">
@yield('content')
</main>
</div>
<script src="{{ asset('js/app.js') }}"></script>
@yield('scripts')
</body>
</html>
This will update the layout file to include the required JavaScript and CSS assets.
Step 12: Run Laravel Development Server
Finally, let’s run the Laravel development server to see our chat application in action. Run the following command in your terminal:
php artisan serve
This will start the Laravel development server on `http://localhost:8000`. Visit this URL in your browser to see the chat application.
Congratulations! You have successfully built a chat application with Laravel Echo and Pusher. Users can now send and receive messages in real-time.
Conclusion
In this tutorial, we learned how to build a real-time chat application using Laravel Echo and Pusher. We covered the following steps:
- Setting up a new Laravel project
- Installing Laravel Echo and Pusher
- Configuring Laravel Echo
- Creating models and migrations for chatrooms, users, and chat messages
- Running migrations
- Creating routes and a controller
- Creating chat views and updating the layout
- Running the Laravel development server
Now, you can further enhance your chat application with features like private messaging, online/offline status, and message notifications.