How to use Laravel Reverb
16458

Laravel Reverb là một máy chủ WebSocket chính thức cho các ứng dụng Laravel, cung cấp khả năng giao tiếp theo thời gian thực giữa máy khách và máy chủ một cách liền mạch.

Laravel Reverb có nhiều tính năng hấp dẫn, bao gồm:

  • Tốc độ và khả năng mở rộng.
  • Hỗ trợ hàng nghìn kết nối đồng thời.
  • Tích hợp với các tính năng phát sóng hiện có của Laravel.
  • Tương thích với Laravel Echo.
  • Tích hợp và triển khai hàng đầu với Laravel Forge.

Trong hướng dẫn này, tôi sẽ hướng dẫn bạn cách sử dụng Laravel Reverb để phát triển một ứng dụng Laravel thời gian thực. Bạn sẽ học về các kênh, sự kiện, phát sóng, và cách sử dụng Laravel Reverb để tạo ra các ứng dụng nhanh chóng và thời gian thực trong Laravel.

Hơn nữa, bạn sẽ học cách thêm thông báo thời gian thực vào ứng dụng Laravel Reverb của mình!

  1. Cài đặt một ứng dụng Laravel mới
    composer create-project laravel/laravel laravel-reverb-chat

    Chuyển đến thư mục dự án của bạn:

    cd laravel-reverb-chat
  2. Installing Laravel Reverb
    Cài đặt Laravel Reverb bằng cách chạy câu lệnh sau:
    php artisan install:broadcasting
    npm install --save laravel-echo pusher-js

    Chú ý: các lựa chọn default

    Sau khi bạn đã cài đặt Reverb, bạn có thể chỉnh sửa cấu hình của nó từ tệp `config / reverb.php`. Để thiết lập kết nối đến Reverb, một bộ thông tin đăng nhập ứng dụng Reverb phải được trao đổi giữa máy khách và máy chủ. Những thông tin đăng nhập này được cấu hình trên máy chủ và được sử dụng để xác minh yêu cầu từ máy khách. Bạn có thể xác định những thông tin đăng nhập này bằng cách sử dụng các biến môi trường sau:

    BROADCAST_DRIVER=reverb
    REVERB_APP_ID=my-app-id
    REVERB_APP_KEY=my-app-key
    REVERB_APP_SECRET=my-app-secret
  3. Running Server
    Bạn có thể khởi chạy máy chủ Reverb bằng cách sử dụng command reverb:start:
    php artisan reverb:start

    Mặc định, máy chủ Reverb sẽ được khởi động tại 0.0.0.0:8080, điều này làm cho nó có thể truy cập từ tất cả các giao diện mạng. Nếu bạn muốn thiết lập một máy chủ hoặc cổng cụ thể, bạn có thể sử dụng các tùy chọn --host--port khi khởi động máy chủ.

    php artisan reverb:start --host=127.0.0.1 --port=9000

    Bạn cũng có thể xác định các biến môi trường REVERB_SERVER_HOST REVERB_SERVER_PORT trong tệp cấu hình .env của ứng dụng của bạn.

  4. Setup Database
    Mở tệp .env của bạn và điều chỉnh cài đặt để thiết lập cơ sở dữ liệu của bạn. Dưới đây là một ví dụ sử dụng MySQL để đơn giản hóa:
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=laravel
    DB_USERNAME=root
    DB_PASSWORD=

    Đối với bản demo này, chúng ta sẽ tạo năm phòng được xác định trước. Hãy bắt đầu bằng cách tạo một migration cho một bảng rooms.

    php artisan make:model Room --migration

    Để đơn giản hóa, chỉ cần tạo trường name cho model này và chạy migration.

    Schema::create('rooms', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
    php artisan migrate

    Sau đó, seed dữ liệu cho database với 5 room. Tạo một seeder:

    php artisan make:seeder RoomsTableSeeder 
    <?php
    
    namespace Database\Seeders;
    
    use Illuminate\Database\Seeder;
    use Illuminate\Support\Facades\DB;
    
    class RoomsTableSeeder extends Seeder
    {
        /**
         * Run the database seeds.
         */
        public function run(): void
        {
            DB::table('rooms')->insert([
                ['name' => 'Room 1'],
                ['name' => 'Room 2'],
                ['name' => 'Room 3'],
                ['name' => 'Room 4'],
                ['name' => 'Room 5'],
            ]);
        }
    }
    
    Run seeder:
    php artisan db:seed --class=RoomsTableSeeder
  5. Tạo Event
    Trong thư mục app/Events, tạo một file mới tên là MessageSent.php. File này chịu trách nhiệm phát sóng các tin nhắn mới tới các phòng chat cụ thể. Dưới đây là mẫu cơ bản:
    php artisan make:event MessageSent

    class MessageSent implements ShouldBroadcast
    {
        use Dispatchable, InteractsWithSockets, SerializesModels;
    
        public $userName;
        public $roomId;
        public $message;
    
        public function __construct($userName, $roomId, $message)
        {
            $this->userName = $userName;
            $this->roomId = $roomId;
            $this->message = $message;
        }
    
        public function broadcastOn() : Channel
        {
    
            return new Channel('chat.' . $this->roomId);
        }
    
        public function broadcastWith()
        {
            return [
                'userName' => $this->userName,
                'message' => $this->message,
            ];
        }
    }
  6. Tạo Pages
    Trong dự án này, chúng ta sẽ có hai trang: một trang để hiển thị danh sách các phòng và một trang cho từng phòng chat riêng biệt. Chúng ta sẽ bắt đầu bằng cách tạo các template Blade để hiển thị các phòng. Đặt tên các view này là index.blade.phpchat.blade.php và lưu chúng trong thư mục rooms dưới resources/views. Tiếp theo, chúng ta sẽ tạo một controller và một route để điều hướng tới các trang này.
    php artisan make:view rooms/index
    php artisan make:view rooms/chat

    index.blade.php
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Chat Rooms</title>
    </head>
    
    <body>
        <div id="app">
            <h1>Chat Rooms</h1>
            <ul>
                @foreach ($rooms as $room)
                    <li>
                        <a href="{{ route('rooms.show', $room->id) }}">Join {{ $room->name }}</a>
                    </li>
                @endforeach
            </ul>
        </div>
    </body>
    
    </html>
    

    chat.blade.php

    Thiết lập một form cơ bản để hiển thị các tin nhắn và một trường nhập liệu đơn giản để gửi tin nhắn. Đảm bảo rằng bạn đã import Echo và Pusher vào file app.js.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Chat Room: {{ $room->name }}</title>
        @vite(['resources/css/app.css'])
        @vite(['resources/js/app.js'])
    </head>
    
    <body>
        <div id="app">
            <h2>Chat Room: {{ $room->name }}</h2>
            <div id="messages"
                style="border: 1px solid #ccc; margin-bottom: 10px; padding: 10px; height: 300px; overflow-y: scroll;">
                <!-- Messages will be displayed here -->
            </div>
            <input type="text" id="messageInput" placeholder="Type your message here..." autofocus>
            <button onclick="sendMessage()">Send</button>
        </div>
    
        <script>
            document.addEventListener('DOMContentLoaded', function() {
                const roomId = "{{ $room->id }}";
                Echo.channel(`chat.${roomId}`)
                    .listen('MessageSent', (e) => {
                        const messages = document.getElementById('messages');
                        const messageElement = document.createElement('div');
                        messageElement.innerHTML = `<strong>${e.userName}:</strong> ${e.message}`;
                        messages.appendChild(messageElement);
                        messages.scrollTop = messages.scrollHeight; // Scroll to the bottom
                    });
            })
    
            function sendMessage() {
                const messageInput = document.getElementById('messageInput');
                const message = messageInput.value;
                messageInput.value = ''; // Clear input
                const roomId = "{{ $room->id }}"
                fetch(`/rooms/${roomId}/message`, {
                    method: 'POST',
                    headers: {
                        'X-CSRF-TOKEN': '{{ csrf_token() }}',
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        message: message
                    })
                }).catch(error => console.error('Error:', error));
            }
        </script>
    </body>
    
    </html>
    

    app.js

    import Echo from 'laravel-echo';
    
    import Pusher from 'pusher-js';
    window.Pusher = Pusher;
    
    window.Echo = new Echo({
        broadcaster: 'reverb',
        key: import.meta.env.VITE_REVERB_APP_KEY,
        wsHost: import.meta.env.VITE_REVERB_HOST,
        wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
        wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
        forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
        enabledTransports: ['ws', 'wss'],
    });

    Tiếp theo hãy tạo Controller

    php artisan make:controller RoomsController
    <?php
    
    namespace App\Http\Controllers;
    
    use App\Models\Room;
    
    class RoomsController extends Controller
    {
        public function index()
        {
            $rooms = Room::all();
            return view('rooms.index', [
                'rooms' => $rooms
            ]);
        }
    
        public function show(Room $room)
        {
            return view('rooms.chat', [
                'roomId' => $room->id,
                'room' => $room,
                'messages' => []
            ]);
        }
    }
    

    Để đơn giản, hãy tạo một endpoint postMessage và thêm nó vào web.php.

    php artisan make:controller ChatController
    <?php
    
    namespace App\Http\Controllers;
    
    use App\Events\MessageSent;
    use Illuminate\Http\Request;
    use Illuminate\Support\Str;
    
    class ChatController extends Controller
    {
        public function postMessage(Request $request, $roomId)
        {
            $userName = 'User_' . Str::random(4);
            $messageContent = $request->input('message');
            MessageSent::dispatch($userName, $roomId, $messageContent);
            return response()->json(['status' => 'Message sent successfully.']);
        }
    }
    
    routes/web.php
    Route::get('/rooms', [RoomsController::class, 'index'])->name('rooms.index');
    Route::get('/rooms/{room}', [RoomsController::class, 'show'])->name('rooms.show');
    Route::post('/rooms/{roomId}/message', [ChatController::class, 'postMessage'])->name('api.rooms.message.post');
  7. Run Project
    Để chạy dự án Laravel, chúng ta cần thực thi các lệnh sau:
    - Khởi động Laravel:
    php artisan serve
    

    - Khởi động frontend:

    npm run dev
    

    - Bắt đầu queue:

    php artisan queue:listen
    

    - Run Reverb:

    php artisan reverb:start
    

Để biết thông tin chi tiết hơn, bạn có thể kiểm tra tài liệu hướng dẫn chính thức của Laravel Reverb. Chúc các bạn thành công

Danh mục


  1. Khác
  2. ThreeJS
  3. Ubuntu/Linux
  4. HTML/CSS
  5. Git
  6. Amazon Web Services
  7. Javascript
  8. Docker
  9. Laravel

Bài viết liên quan


Ví dụ về các vấn đề truy vấn N+1

Ví dụ về các vấn đề truy vấn N+1

01.08.2024
Author: ADMIN
Tìm hiểu vấn đề N+1 Query trong Eloquent Laravel, cách phát hiện và tối ưu hóa với Eager Loading, withCount, và Strict Loading Mode để cải thiện hiệu suất ứng dụng.
Tiết Kiệm Thời Gian và Công Sức với Laravel Auto CRUD Generator

Tiết Kiệm Thời Gian và Công Sức với Laravel Auto CRUD Generator

13.03.2025
Author: ADMIN
Laravel Auto CRUD Generator là công cụ tự động tạo CRUD cho các mô hình Laravel, giúp tiết kiệm thời gian và công sức phát triển ứng dụng. Chỉ cần một lệnh duy nhất để tạo controller, request validation, routes, views, và nhiều hơn nữa.

Bài viết khác

Routing

Routing

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về Basic Routing trong Laravel, từ cách định nghĩa route, sử dụng middleware, route caching đến route naming giúp tối ưu hóa ứng dụng.
Blade Basics

Blade Basics

01.08.2024
Author: ADMIN
Khám phá Blade trong Laravel: từ if-else, loops, kế thừa layout đến include sub-views. Giúp code gọn gàng, dễ quản lý và bảo trì hơn!
9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

01.08.2024
Author: ADMIN
Khám phá 9 mẹo Blade giúp bạn viết code Laravel sạch, tối ưu và chuyên nghiệp hơn. Từ @forelse, @auth, @guest, đến format ngày, tối ưu SEO – tất cả trong một bài viết súc tích, dễ áp dụng!
Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN
Hướng dẫn hiển thị biến trong Laravel Blade: escape HTML tự động, hiển thị dữ liệu thô, giá trị mặc định và cách truy xuất mảng, đối tượng. Giúp bạn tối ưu hiển thị dữ liệu một cách an toàn!