Giới thiệu về laravel echo ứng dụng websocket và vuejs

Những ứng dụng hay không thể thiếu WebSockets được. Bạn có thể làm Tool chat online, Notification, ... và rất nhiều những ứng dụng real time khác. Với Laravel Echo mọi thứ càng trở nên đơn giản.

Ý tưởng

Xây dựng chức năng chát trực tuyến với multiple rooms.

Laravel Echo

Hình dung trước khi làm

Ứng dụng Chat online thì chắc chắn cần 1 WebSocket để lắng nghe dữ liệu gửi lên rồi. Ok sử dụng laravel-echo-server cho nó máu. Phía client khi nhận được dữ liệu từ Broadcasting sẽ hiển thị dữ liệu trực tiếp tới người dùng, chơi luôn Vuejs.

Bắt đầu thôi

Đầu tiên tạo 1 event trong Laravel

php artisan make:event ChatMessageWasReceived

Kiểm tra có file nào mới không nào app/Events/ChatMessageWasReceived.php done!

Trong file có 1 method khá quan trọng

public function broadcastOn()
{
    return new PrivateChannel('channel-name');
}

Để đơn giản mình sẽ ko sử dụng Private channel nữa mà sử dụng Public channel trong bài này thay đổi lại sẽ như sau

public function broadcastOn()
{
    return [
        "chat-room.1"
    ];
}

Tiếp theo ứng dụng chat phải có nơi lưu trữ dữ liệu, Tiến hành tạo migration thôi.

php artisan make:model ChatMessage --migration

Với nội dung khá đơn giản

...
class CreateChatMessagesTable extends Migration
{
    public function up()
    {
        Schema::create('chat_messages', function (Blueprint $table) {
            $table->increments('id');
            $table->string('message');
            $table->integer('user_id')->unsigned();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop('chat_messages');
    }
}

Quay trở lại với class app/Events/ChatMessageWasReceived.php truyền 1 số tham số vào như sau

...
class ChatMessageWasReceived extends Event implements ShouldBroadcast
{
    use InteractsWithSockets, SerializesModels;

    public $chatMessage;
    public $user;

    public function __construct($chatMessage, $user)
    {
        $this->chatMessage = $chatMessage;
        $this->user = $user;
    }

    public function broadcastOn()
    {
        return [
            "chat-room.1"
        ];
    }
}

Các bạn nhớ Implements ShouldBroadcast interface vào nhé.

Ok rồi bây giờ mình sẽ sử dụng Command để gửi đi 1 thông điệp cho client. Tạo 1 command thôi

php artisan make:command SendChatMessage

1 file mới được sinh ra app/Console/Commands/SendChatMessage.php có nội dung như sau

...
class SendChatMessage extends Command
{
    protected $signature = 'chat:message {message}';

    protected $description = 'Send chat message.';

    public function handle()
    {
        // Fire off an event, just randomly grabbing the first user for now
        $user = \App\User::first();
        $message = \App\ChatMessage::create([
            'user_id' => $user->id,
            'message' => $this->argument('message')
        ]);

        event(new \App\Events\ChatMessageWasReceived($message, $user));
    }
}

Open app/Console/Kernel.php và thêm vào params như sau

...
class Kernel extends ConsoleKernel
{
    protected $commands = [
        Commands\SendChatMessage::class,
    ];
...

Ok vậy là xong Bây giờ mỗi khi gửi 1 thông điệp chúng ta sẽ sử dụng command như sau

php artisan chat:message "Howdy everyone"

Ok thông điệp này sẽ được gửi tới đâu, Mình sẽ gửi nó đến 1 websocket để nhận dữ liệu như bên trên mình đã nói sẽ sử dụng laravel-echo-server

 npm install -g laravel-echo-server

Khi đã kéo xong package laravel-echo-server

Khởi tạo cho project

laravel-echo-server init

Nó sẽ sinh ra 1 file laravel-echo-server.json Các bạn cấu hình file đó theo môi trường của các bạn nhé, Ở đây mình sẽ sử dụng redis làm db và open port 6001 default của broadcast.

Open file .env và cấu hình tiếp broadcast như sau

BROADCAST_DRIVER=redis
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

Khởi động WebSocket

laravel-echo-server start

Các bạn có thể check port 6001 đã hoạt động chưa nhé với linux

netstat -antp | grep LISTEN

Nếu thấy port 6001 đang lắng nghe thì đã thành công rồi đó. *_^

Tiếp theo config tiếp để client nhận được thông tin. Open resouces/assets/js/app.js và thêm vào nội dung sau

import Echo from "laravel-echo"

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: 'http://yourdomain.dev:6001'
});

Echo.channel('chat-room.1')
    .listen('ChatMessageWasReceived', (e) => {
        console.log(e.user, e.chatMessage);
    });

Khá ổn rồi đây bây giờ hãy chạy gulp hoặc gulp watch .

Chèn vào HTML 2 file javascript sau

<html>
    <head>
        ...
        <meta name="csrf-token" content="{{ csrf_token() }}">
        ...
    </head>
    <body>
        ...

        <script src="js/app.js"></script>
        <script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
    </body>
</html>

Vậy là hoàn thành. Các bạn có thể test thử

php artisan chat:message "Howdy everyone"

Thông điệp trên sẽ được lưu vào database và truyền lên cho WebSocket qua port 6001 sử dụng protocol TCP sau đó gửi lại phía client để Laravel Echo nhận thông điệp và hiển thị cho các bạn qua consolog. Cứ mỗi lần gửi thông điệp lên là consolog lại hiển thị dữ liệu ngay lập tức. Bài viết cũng khá dài rồi mình sẽ không hướng dẫn cụ thể để làm hoàn chỉnh 1 ứng dụng chat sử dụng vuejs nữa. Mình sẽ để dành nó vào bài sau vậy. Cảm ơn các bạn đã đọc. Chúc các bạn thành công nhé .!

Reference

Bài viết có tham khảo qua các tài liệu

https://mattstauffer.co/blog/introducing-laravel-echo https://laravel.com/docs/5.3/broadcasting#defining-broadcast-events https://laracasts.com/lessons/introducing-laravel-echo