DEV Community

Richardson
Richardson

Posted on

Implementing realtime chat and notifications in an Airbnb clone with Laravel and WebSocket

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:

  1. Laravel Project: Have a Laravel project up and running.

  2. Pusher Account: Sign up for a free Pusher account (https://pusher.com/) and create a new app. You'll need the app credentials.

  3. 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
Enter fullscreen mode Exit fullscreen mode

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,
        ],
    ],
],
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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();
    });
}
Enter fullscreen mode Exit fullscreen mode

Run the migration to create the chats table:

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

Step 3: Create ChatController

Generate a controller for handling chat messages:

php artisan make:controller ChatController
Enter fullscreen mode Exit fullscreen mode

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]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create an Event

Generate an event to broadcast new chat messages:

php artisan make:event NewChatMessage
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

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)