Building a Real-Time Chat Application with Laravel and Pusher

İbrahim Halil Oğlakcı
3 min readJul 24, 2024

--

Introduction

In this tutorial, we will build a real-time chat application using Laravel and Pusher. This guide assumes you have a senior-level understanding of Laravel and real-time messaging systems. We will cover setting up Laravel, integrating Pusher, and implementing real-time notifications. By the end, you’ll have a fully functional chat application with code examples.

Prerequisites

Before we start, make sure you have the following:

  • PHP 7.3+ and Composer installed
  • Laravel 8+ installed
  • Pusher account
  • Basic understanding of Laravel, JavaScript, and Pusher

Setting Up Laravel Project

First, create a new Laravel project:

composer create-project --prefer-dist laravel/laravel chat-app

Navigate into your project directory:

cd chat-app

Set up your .env file with your database configuration:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=chat_app
DB_USERNAME=root
DB_PASSWORD=

Run the migrations to create the necessary tables:

php artisan migrate

Setting Up Pusher

Install the Pusher PHP SDK:

composer require pusher/pusher-php-server

Register your Pusher credentials in the .env file:

PUSHER_APP_ID=your-pusher-app-id
PUSHER_APP_KEY=your-pusher-app-key
PUSHER_APP_SECRET=your-pusher-app-secret
PUSHER_APP_CLUSTER=mt1

Configure broadcasting settings in config/broadcasting.php:

'default' => env('BROADCAST_DRIVER', 'pusher'),

'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
],
],

Creating the Models and Migrations

We’ll need User and Message models. First, create the Message model and migration:

php artisan make:model Message -m

Edit the migration file to define the schema:

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

Run the migration:

php artisan migrate

Setting Up Event Broadcasting

Create a new event for message broadcasting:

php artisan make:event MessageSent

Edit the event file app/Events/MessageSent.php:

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
use App\Models\Message;

class MessageSent implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;

public $message;

public function __construct(Message $message)
{
$this->message = $message;
}

public function broadcastOn()
{
return new PrivateChannel('chat');
}
}

Creating the Message Controller

Create a controller to handle message sending:

php artisan make:controller MessageController

Edit app/Http/Controllers/MessageController.php:

use App\Events\MessageSent;
use App\Models\Message;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class MessageController extends Controller
{
public function sendMessage(Request $request)
{
$message = Message::create([
'user_id' => Auth::id(),
'message' => $request->message
]);

broadcast(new MessageSent($message))->toOthers();

return response()->json(['status' => 'Message Sent!']);
}

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

Setting Up Routes

Add the following routes to routes/web.php:

use App\Http\Controllers\MessageController;

Route::get('/messages', [MessageController::class, 'fetchMessages']);
Route::post('/messages', [MessageController::class, 'sendMessage']);

Creating the Frontend

In resources/views/welcome.blade.php, add the following HTML and JavaScript:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat App</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://js.pusher.com/7.0/pusher.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
</head>
<body>
<div class="container">
<div class="row" id="app">
<div class="col-12">
<h1>Chat App</h1>
<ul id="messages" class="list-group">
<!-- Messages will be loaded here -->
</ul>
<form id="message-form">
<div class="form-group">
<input type="text" id="message-input" class="form-control" placeholder="Type your message...">
</div>
<button type="submit" class="btn btn-primary">Send</button>
</form>
</div>
</div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
const messagesElement = document.getElementById('messages');
const messageForm = document.getElementById('message-form');
const messageInput = document.getElementById('message-input');

// Fetch messages
axios.get('/messages').then(response => {
response.data.forEach(message => {
addMessage(message);
});
});

// Listen for new messages
Echo.private('chat')
.listen('MessageSent', (e) => {
addMessage(e.message);
});

// Add message to list
function addMessage(message) {
const messageElement = document.createElement('li');
messageElement.classList.add('list-group-item');
messageElement.textContent = message.user.name + ': ' + message.message;
messagesElement.appendChild(messageElement);
}

// Send message
messageForm.addEventListener('submit', function(e) {
e.preventDefault();

const message = messageInput.value;
axios.post('/messages', { message }).then(response => {
messageInput.value = '';
});
});
});
</script>
<script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>
<script src="{{ mix('js/app.js') }}"></script>
</body>
</html>

Conclusion

In this tutorial, we built a real-time chat application using Laravel and Pusher. We covered setting up Laravel, integrating Pusher, creating models and controllers, setting up event broadcasting, and creating a frontend for real-time messaging. With this foundation, you can expand the application with features like private messaging, notifications, and more advanced user interactions. Happy coding!

--

--

İbrahim Halil Oğlakcı
İbrahim Halil Oğlakcı

Responses (1)