Creating real-time features like chat or notifications between hosts and guests is a crucial part of building a seamless Airbnb clone experience. Laravel, with the help of WebSockets, can be a great choice for implementing this functionality.
In this blog post, we will walk through the process of setting up a real-time chat and notification system using Laravel, the Laravel Echo package, and the Pusher service. We'll use a simplified example to illustrate the key steps involved.
Prerequisites
Before getting started, make sure you have the following components set up:
Laravel Project: Have a Laravel project up and running.
Pusher Account: Sign up for a free Pusher account (https://pusher.com/) and create a new app. You'll need the app credentials.
Laravel Echo: Install the Laravel Echo package in your project using
composer require laravel/echo
.
Step 1: Setting up Laravel Echo and Pusher
First, configure Laravel Echo and Pusher. Open your .env
file and set the following variables:
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_APP_CLUSTER=your-app-cluster
Next, update the config/broadcasting.php
file to use the Pusher driver:
'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'),
'encrypted' => true,
],
],
],
Step 2: Create the Chat Model and Migration
Let's create a model and migration for our chat system. Run the following commands:
php artisan make:model Chat -m
In the generated migration file, define the chats
table schema:
public function up()
{
Schema::create('chats', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('sender_id');
$table->unsignedBigInteger('receiver_id');
$table->text('message');
$table->timestamps();
});
}
Run the migration to create the chats
table:
php artisan migrate
Step 3: Create ChatController
Generate a controller for handling chat messages:
php artisan make:controller ChatController
In the ChatController
, create methods for sending and retrieving chat messages. Here's a simplified example:
use Illuminate\Http\Request;
use App\Events\NewChatMessage;
use App\Chat;
class ChatController extends Controller
{
public function send(Request $request)
{
$message = Chat::create([
'sender_id' => auth()->id(),
'receiver_id' => $request->receiver_id,
'message' => $request->message,
]);
broadcast(new NewChatMessage($message))->toOthers();
return response()->json(['message' => 'Message sent']);
}
public function getMessages(Request $request)
{
$messages = Chat::where(function ($query) use ($request) {
$query->where('sender_id', auth()->id())
->where('receiver_id', $request->receiver_id);
})->orWhere(function ($query) use ($request) {
$query->where('sender_id', $request->receiver_id)
->where('receiver_id', auth()->id());
})->get();
return response()->json(['messages' => $messages]);
}
}
Step 4: Create an Event
Generate an event to broadcast new chat messages:
php artisan make:event NewChatMessage
In the NewChatMessage
event, define the data to be broadcasted:
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Chat;
class NewChatMessage
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public function __construct(Chat $message)
{
$this->message = $message;
}
public function broadcastOn()
{
return new PrivateChannel('chat.' . $this->message->receiver_id);
}
}
Step 5: Configure Broadcasting Channels
Define the broadcasting channels in routes/channels.php
. In this case, we're using private channels for one-on-one chats:
use Illuminate\Support\Facades\Broadcast;
use App\User;
Broadcast::channel('chat.{receiver_id}', function ($user, $receiver_id) {
return $user->id === (int) $receiver_id;
});
Step 6: Set Up the Frontend
On the frontend, you'll need to use Laravel Echo to listen for incoming messages and send messages to the server. Here's an example using JavaScript and Vue.js:
// resources/js/bootstrap.js
import Echo from 'laravel-echo'
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true,
authEndpoint: '/broadcasting/auth',
})
// resources/js/components/ChatComponent.vue
<template>
<div>
<div v-for="message in messages" :key="message.id">
{{ message.message }}
</div>
<input v-model="newMessage" @keyup.enter="sendMessage" />
</div>
</template>
<script>
export default {
data() {
return {
messages: [],
newMessage: '',
}
},
created() {
this.fetchMessages()
this.listenForMessages()
},
methods: {
fetchMessages() {
// Make an API request to get chat messages
},
listenForMessages() {
Echo.private('chat.' + this.receiverId)
.listen('NewChatMessage', (event) => {
this.messages.push(event.message)
})
},
sendMessage() {
// Make an API request to send a chat message
},
},
}
</script>
Step 7: Create the API Routes
Create API routes for sending and retrieving chat messages:
// routes/api.php
Route::middleware('auth:api')->group(function () {
Route::post('/chat/send', 'ChatController@send');
Route::get('/chat/messages', 'ChatController@getMessages');
});
Step 8: Secure the API Routes
To secure the API routes, you can use Laravel Passport for authentication and authorization. Make sure the routes are protected and only accessible by authenticated users.
Step 9: Test the Chat System
With everything set up, you can now test your chat system by sending and receiving messages in real-time between hosts and guests.
Conclusion
Implementing real-time features like chat or notifications using Laravel and WebSockets can significantly enhance the user experience of your Airbnb clone.
This blog post provided a simplified example of how to set up a real-time chat system using Laravel, Laravel Echo, and Pusher. You can expand on this foundation to create a full-featured chat and notification system for your application, giving your users a seamless and engaging experience.
Thank you.
Top comments (0)