LARAVEL TUTORIALS
10 thủ thuật Lavavel giúp bạn code nhanh hơn! Routing trong Laravel, cách tạo Route và sử dung AZ Tạo Middleware trong Laravel đơn giản trong 5 phút Xử lý Authentication và Authorization trong Laravel Event và listener trong Laravel, cách tạo và quản lý cơ bản nhất Tạo broadcast event trong Laravel dễ dàng trong 10 phút Xử lý Form Validation trong Laravel từ A - Z Cách tạo Session và cookie trong Laravel dễ dàng như ăn cháo Top 10 Package Lavavel thường dùng trong dự án Laravel Sử dụng Task trong Laravel đơn giản trong 10 phút. Cách tạo API trong Laravel đơn giản chỉ trong 5 phút Cách tạo job trong Laravel sao cho hiệu quả? Queues trong Laravel, dùng để xử lý các tác vụ mất nhiều thời gian Cache trong Laravel, các loại Cache thường dùng trong Laravel Redis trong Laravel, biết cách sử dung Redis Laravel trong 5 phút Sử dụng Memcache trong Laravel tăng tốc độ truy cập website Unit Test trong Laravel, thực hành tạo testing Laravel A-Z 10 thủ thuật tối ưu quá trình Testing trong Laravel Top 7 thư viện Testing Laravel được dùng nhiều nhất Testbench và Orchestra Testbench trong Laravel, kiểm thử Laravel dễ dàng Cách dùng Browser Testing (Laravel Dusk) trong Laravel Cách tạo test case cho Controller trong Laravel Cách tạo test case cho Model trong Laravel Cách tạo Database Testing trong Laravel Real-time web applications là gì ? Tầm quan trọng trong Laravel Laravel WebSockets, các bước tạo WebSockets trong Laravel Cách dùng Socket.io trong Laravel để tạo ứng dụng realtime Dùng Server-Sent Events trong Laravel để làm ứng dụng realtime Cách dùng Long polling trong Laravel để cải thiện trải nghiệm Cách tích hợp Vue.js vào Laravel và làm một ứng dụng căn bản Task Scheduling là gì? Cấu hình Task Scheduling trong Laravel Cách dùng Queue trong laravel để tạo tác vụ bất đồng bộ Cách dùng Event Sourcing trong Laravel Cách sử dụng CQRS trong Laravel từ A đến Z đơn giản Sử dụng Service Container trong Laravel dễ dàng Cách xử lý đa ngôn ngữ trong Laravel dễ dàng Tìm hiểu và sử dụng Service Provider trong Laravel Facades là gì? Cách dùng Facades trong Laravel Cách sử dụng Email Verification trong Laravel Cách dùng URL Generation trong Larevel Cách sử dụng Error Handling trong Laravel Cách dùng Encryption và decryption trong Laravel Cách sử dụng Relationships trong Laravel Bài 01: Laravel là gì? Hướng dẫn cài đặt laravel trên windows Sử dụng Event trong Laravel Một cách quản lý filter trong Laravel
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Dùng Server-Sent Events trong Laravel để làm ứng dụng realtime

Vì sao Server-Sent Events là một phương pháp truyền tải dữ liệu realtime được ưa chuộng trong phát triển ứng dụng web và có gì khác biệt so với các phương pháp khác như WebSockets?

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Trong bài viết này, chúng ta sẽ tìm hiểu về cách sử dụng Server-Sent Events trong Laravel, một trong những framework web phổ biến nhất hiện nay. Chúng ta sẽ cùng nhau tìm hiểu về SSE, cách cài đặt SSE trong Laravel, cách xây dựng ứng dụng SSE và những ưu nhược điểm của SSE để hiểu rõ hơn về công nghệ này và ứng dụng nó trong phát triển ứng dụng web.

1. Server-Sent Events (SSE) là gì?

SSE laravel jpg

Server-Sent Event (SSE)

Server-Sent Events (SSE) là một công nghệ truyền tải dữ liệu realtime từ server đến client thông qua HTTP protocol. Với SSE, server có thể gửi thông tin đến client mà không cần client gửi yêu cầu (request) trước đó. SSE được xem là một trong những phương pháp tiên tiến để tạo ra trải nghiệm người dùng tốt nhất và được ưa chuộng trong việc xây dựng ứng dụng web realtime như chat, notification hay live updates.

2. Tại sao nên sử dụng SSE trong ứng dụng web?

SSE cung cấp nhiều lợi ích cho việc xây dựng ứng dụng web realtime. Một số lợi ích của SSE như sau:

Bài viết này được đăng tại [free tuts .net]

  • Không cần thiết lập kết nối mới cho mỗi request, giúp giảm tải cho server.
  • Không cần sử dụng thư viện bên ngoài, SSE được hỗ trợ trực tiếp trong các trình duyệt hiện đại.
  • SSE cho phép server gửi thông tin mới nhất tới client ngay khi nó có sẵn, giúp cập nhật thông tin realtime mà không cần phải tải lại trang.
  • SSE là một giải pháp phù hợp cho các ứng dụng realtime như chat, notification hay live updates mà không cần phải sử dụng WebSockets.

Tóm lại, SSE là một phương pháp hiệu quả để truyền tải dữ liệu realtime trong ứng dụng web và cung cấp nhiều lợi ích cho việc xây dựng các ứng dụng realtime.

3. Cách sử dụng SSE trong Laravel

Cài đặt thư viện phía server

Để sử dụng SSE trong Laravel, ta cần cài đặt một số thư viện bổ sung. Trong trường hợp này, ta sẽ sử dụng thư viện Spatie\EventSourcing.

Bước 1: Sử dụng Composer để cài đặt thư viện Spatie\EventSourcing.

composer require spatie/event-sourcing

Bước 2: Publish các file cấu hình của thư viện.

php artisan vendor:publish --provider="Spatie\EventSourcing\EventSourcingServiceProvider" --tag="config"

Cài đặt thư viện phía client

Để sử dụng SSE trên phía client, ta cần sử dụng JavaScript để lắng nghe sự kiện SSE. Thư viện EventSource của HTML5 cung cấp các API để kết nối tới SSE.

Bước 1: Tạo một file JavaScript để kết nối tới SSE và lắng nghe sự kiện.

var source = new EventSource('/sse');

source.addEventListener('message', function(event) {
    console.log('Received message: ' + event.data);
});

source.addEventListener('open', function(event) {
    console.log('Connected to SSE.');
});

source.addEventListener('error', function(event) {
    if (event.target.readyState === EventSource.CLOSED) {
        console.log('Disconnected from SSE.');
    } else {
        console.log('Error occurred while connecting to SSE.');
    }
});

Bước 2: Thêm đoạn mã JavaScript vào file view của Laravel.

<script src="{{ asset('js/sse.js') }}"></script>

Tạo route SSE trong Laravel

Bước 1: Tạo một route trong file web.php.

Route::get('/sse', function () {
    $response = new \Symfony\Component\HttpFoundation\StreamedResponse(function () {
        while (true) {
            echo "data: " . json_encode(['message' => 'Hello world']) . "\n\n";
            ob_flush();
            flush();
            sleep(1);
        }
    });

    $response->headers->set('Content-Type', 'text/event-stream');
    $response->headers->set('Cache-Control', 'no-cache');

    return $response;
});

Trong ví dụ trên, route /sse sẽ trả về một response có kiểu text/event-stream và sử dụng phương thức StreamedResponse của Symfony để gửi dữ liệu realtime tới client. Trong hàm StreamedResponse, ta sử dụng vòng lặp vô hạn để gửi thông tin realtime tới client. Trong ví dụ này, ta sẽ gửi một chuỗi JSON có nội dung {'message': 'Hello world'} tới client sau mỗi giây.

Bước 2: Truy cập route /sse để kết nối tới SSE.

Sau khi đã cài đặt thư viện phía server và client, bây giờ ta có thể bắt đầu sử dụng Server-Sent Events trong Laravel.

Để tạo một SSE endpoint, ta cần tạo một route trong file routes/web.php. Ví dụ:

use App\Http\Controllers\SSEController;

Route::get('/sse', [SSEController::class, 'stream'])->name('sse');

Trong đoạn code trên, ta đã tạo một route /sse và liên kết nó với một action stream() trong SSEController.

Trong SSEController, ta sẽ tạo một hàm stream() để trả về response dạng SSE. Ví dụ:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;

class SSEController extends Controller
{
    public function stream(Request $request)
    {
        $response = new StreamedResponse(function () {
            // Các bước xử lý SSE
        });

        $response->headers->set('Content-Type', 'text/event-stream');
        $response->headers->set('Cache-Control', 'no-cache');
        $response->headers->set('X-Accel-Buffering', 'no');

        return $response;
    }
}

Trong hàm stream(), ta tạo một instance của StreamedResponse để tạo ra response dạng SSE. Trong constructor của StreamedResponse, ta truyền vào một closure để thực hiện các bước xử lý SSE.

Trong closure này, ta sẽ đầu tiên gửi một message SSE bằng cách sử dụng thư viện php-redis đã cài đặt ở bước trước đó:

use Illuminate\Support\Facades\Redis;

Redis::publish('sse-channel', json_encode(['message' => 'Hello world!']));

Trong đoạn code trên, ta gửi một message SSE với nội dung là Hello world! tới kênh sse-channel bằng cách sử dụng Redis::publish().

Tiếp theo, ta sẽ thiết lập các header cho response dạng SSE bằng cách sử dụng các phương thức của đối tượng StreamedResponse.

Sau khi đã tạo xong SSE endpoint, ta có thể sử dụng EventSource để kết nối tới endpoint đó từ phía client và nhận các message SSE được gửi từ server. Ví dụ:

const source = new EventSource('/sse');

source.addEventListener('message', function(event) {
    console.log('Received SSE message: ' + event.data);
});

Trong đoạn code trên, ta đã tạo một instance của EventSource với địa chỉ là /sse. Khi server gửi một message SSE tới endpoint này, sự kiện message sẽ được kích hoạt và callback được định nghĩa trong hàm addEventListener() sẽ được thực thi.

Sử dụng SSE trong Laravel

Sau khi đã cài đặt thư viện phía server và client, chúng ta có thể sử dụng SSE trong Laravel bằng cách tạo ra một route để xử lý yêu cầu SSE từ client. Để làm điều này, ta cần đăng ký một route trong file web.php như sau:

Route::get('/sse', function () {
    return view('sse');
});

Trong đoạn code trên, chúng ta đã đăng ký một route có đường dẫn /sse và trả về view sse.blade.php khi có yêu cầu từ client.

Tiếp theo, chúng ta sẽ tạo view sse.blade.php để xử lý SSE từ phía server. Đầu tiên, ta cần tạo ra một đối tượng Symfony\Component\HttpFoundation\StreamedResponse để gửi response SSE cho client. Để làm điều này, ta sử dụng hàm response()->stream() của Laravel như sau:

use Symfony\Component\HttpFoundation\StreamedResponse;

return response()->stream(function () {
    $data = 'Hello, world!';
    $event = 'message';
    $id = '123';
    echo "event: $event\n";
    echo "id: $id\n";
    echo "data: $data\n\n";
    ob_flush();
    flush();
}, 200, ['Content-Type' => 'text/event-stream']);

Trong đoạn code trên, chúng ta đã sử dụng hàm response()->stream() để trả về một đối tượng StreamedResponse. Đối số đầu tiên của hàm này là một closure để xử lý dữ liệu SSE cho client. Trong closure này, ta đã tạo ra ba biến $data, $event $id để định dạng SSE message. Sau đó, ta sử dụng các lệnh echo để gửi message SSE cho client. Lưu ý rằng chúng ta phải sử dụng ký tự xuống dòng \n\n để đánh dấu kết thúc của một message SSE. Cuối cùng, ta sử dụng các hàm ob_flush() và flush() để đảm bảo rằng response được gửi về client một cách liền mạch.

Tiếp theo, ta cần sử dụng JavaScript để nhận dữ liệu SSE từ phía server. Để làm điều này, ta sử dụng đoạn mã JavaScript sau:

const eventSource = new EventSource('/sse');

eventSource.addEventListener('message', (event) => {
    console.log(event.data);
});

eventSource.addEventListener('error', (event) => {
    console.error('Server-Sent Event error:', event);
});

Trong đoạn code trên, chúng ta đã tạo một đối tượng EventSource để kết nối tới đường dẫn /sse của server.

Tạo route SSE

Tiếp theo, bạn cần tạo một route SSE trong file web.php. Route này sẽ nhận các kết nối SSE từ client và trả về các sự kiện.

Trong ví dụ này, chúng ta sẽ tạo một route SSE tên là /sse. Route này sẽ trả về các sự kiện đang diễn ra.

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;

Route::get('/sse', function (Request $request) {
    $response = new StreamedResponse();

    $response->setCallback(function () {
        $data = ['message' => 'Hello, world!'];

        echo 'data: ' . json_encode($data) . PHP_EOL;
        echo PHP_EOL;

        ob_flush();
        flush();

        sleep(5);
    });

    $response->headers->set('Content-Type', 'text/event-stream');
    $response->headers->set('Cache-Control', 'no-cache');

    return $response;
});

Trong hàm callback, chúng ta đang trả về một message chứa đựng dữ liệu "Hello, world!". Để đảm bảo các sự kiện được trả về đến client một cách liên tục, chúng ta sử dụng hàm sleep để đợi 5 giây trước khi trả về kết quả tiếp theo.

Test ứng dụng

Bây giờ, chúng ta đã hoàn tất việc cài đặt SSE trong Laravel. Bạn có thể chạy ứng dụng và truy cập vào route /sse để kiểm tra các sự kiện được trả về từ server.

Để test SSE trong Laravel, bạn có thể sử dụng trình duyệt Chrome và công cụ Developer Tools để xem các sự kiện được trả về từ server.

4. Xây dựng ứng dụng SSE trong Laravel

Bước 1: Cài đặt package

Sử dụng composer để cài đặt package "laravel-sse" bằng cách chạy lệnh sau trong terminal:

composer require marchie/laravel-s

Bước 2: Thiết kế API SSE

Tạo một route trong file routes/web.php để xử lý kết nối SSE và gửi dữ liệu:

use Marchie\SSE\SSE;

Route::get('/stream', function () {
    $sse = new SSE();
    $sse->addEventListener('message', function () {
        $data = [
            'time' => date('H:i:s'),
            'message' => 'Hello, SSE!'
        ];
        return json_encode($data);
    });
    $sse->start();
});

Trong ví dụ này, chúng ta tạo một SSE đơn giản gửi một tin nhắn "Hello, SSE!" cùng với thời gian hiện tại.

Bước 3: Tạo trang hiển thị thông tin realtime

Tạo một trang HTML để hiển thị thông tin realtime sử dụng SSE bằng cách đăng ký event listener cho object SSE. Trong ví dụ này, chúng ta sử dụng file resources/views/stream.blade.php:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>SSE Demo</title>
</head>
<body>
    <h1>Realtime Messages</h1>
    <ul id="messages"></ul>
    <script>
        var source = new EventSource("/stream");
        source.addEventListener('message', function(event) {
            var data = JSON.parse(event.data);
            var messages = document.getElementById("messages");
            var li = document.createElement("li");
            li.innerHTML = "[" + data.time + "] " + data.message;
            messages.appendChild(li);
        });
    </script>
</body>
</html>

Trong trang HTML này, chúng ta sử dụng EventSource để kết nối đến route SSE và đăng ký một event listener để hiển thị dữ liệu realtime. Mỗi lần có một tin nhắn mới được gửi từ API SSE, chúng ta sẽ thêm nó vào danh sách hiển thị.

Bước 4: Tạo script javascript để kết nối tới API SSE và nhận thông tin realtime

Thêm script vào file resources/js/app.js để kết nối đến API SSE và hiển thị dữ liệu realtime:

require('./bootstrap');

var source = new EventSource("/stream");
source.addEventListener('message', function(event) {
    var data = JSON.parse(event.data);
    console.log(data);
});

Chúng ta sử dụng EventSource để kết nối đến route SSE và đăng ký một event listener để hiển thị dữ liệu realtime trong console của trình duyệt.

Cập nhật file layout

Cuối cùng, chúng ta cần cập nhật file layout resources/views/layouts/app.blade.php để sử dụng trang SSE và script javascript:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ config('app.name', 'Laravel') }}</title>
<link rel="stylesheet" href="{{ mix('css/app.css') }}">

</head>
<body>
    <div id="app">
        @yield('content')
    </div>
    <script src="{{ mix('js/app.js') }}"></script>
</body>
</html>

Chúng ta thêm đoạn script <script src="{{ mix('js/app.js') }}"></script> để kết nối tới API SSE.

Với các bước trên, bạn đã xây dựng xong ứng dụng SSE trong Laravel. Bây giờ, bạn có thể truy cập vào trang /stream để xem các tin nhắn realtime và kiểm tra console của trình duyệt để xem thông tin chi tiết.

5. Ưu điểm và nhược điểm của SSE

Ưu điểm của SSE

Realtime: SSE cho phép gửi dữ liệu từ server tới client trong thời gian thực, giúp các ứng dụng web hoạt động nhanh và hiệu quả hơn.

Dễ sử dụng: SSE là một giao thức đơn giản và dễ sử dụng, chỉ cần sử dụng một vài API của trình duyệt để kết nối tới server và nhận dữ liệu realtime.

Hiệu suất cao: SSE sử dụng kết nối HTTP đơn giản, giúp giảm thiểu tài nguyên mạng và tăng hiệu suất cho các ứng dụng web.

Hỗ trợ trình duyệt rộng rãi: SSE được hỗ trợ trên hầu hết các trình duyệt hiện đại, bao gồm cả trên thiết bị di động.

Dữ liệu có thể tuần tự: SSE cho phép gửi dữ liệu có thứ tự từ server tới client, giúp việc hiển thị thông tin trên giao diện người dùng dễ dàng hơn.

Nhược điểm của SSE

Không hỗ trợ truyền dữ liệu hai chiều: SSE chỉ cho phép truyền dữ liệu từ server tới client, không thể truyền dữ liệu ngược lại từ client tới server.

Chỉ hỗ trợ trình duyệt mới: SSE không được hỗ trợ trên các trình duyệt cũ, điều này có thể gây ra vấn đề về tương thích khi phát triển ứng dụng.

Thời gian delay có thể xảy ra: Mặc dù SSE là một giao thức realtime, thời gian delay có thể xảy ra trong trường hợp mạng bị chậm hoặc kết nối bị gián đoạn.

Giới hạn về số lượng kết nối: SSE không được thiết kế để xử lý hàng trăm hoặc hàng nghìn kết nối cùng lúc, điều này có thể gây ra vấn đề về hiệu suất và khả năng mở rộng của ứng dụng.

Kết bài viết

Trong kết luận, có thể khẳng định rằng việc sử dụng Server-Sent Events (SSE) trong Laravel là một lựa chọn tốt cho các lập trình viên muốn xây dựng các ứng dụng web realtime.

SSE cho phép truyền dữ liệu từ server tới client trong thời gian thực, giúp cải thiện hiệu suất và trải nghiệm người dùng của ứng dụng web. SSE cũng giúp giảm tải cho server bằng cách chỉ gửi dữ liệu khi cần thiết.

Trong Laravel, việc sử dụng SSE rất đơn giản nhờ vào package laravel-sse, giúp chúng ta tiết kiệm thời gian và công sức trong việc xây dựng ứng dụng SSE. SSE cũng hỗ trợ trên hầu hết các trình duyệt hiện đại, đảm bảo tính tương thích và khả năng mở rộng cho ứng dụng.

Việc sử dụng SSE trong Laravel cho phép các lập trình viên xây dựng các ứng dụng web realtime tốt hơn, đáp ứng nhu cầu của người dùng và tạo ra trải nghiệm người dùng tốt hơn. Nó là một công nghệ quan trọng trong việc phát triển các ứng dụng web và có thể sẽ trở thành xu hướng phát triển trong tương lai.

Cùng chuyên mục:

Cách sử dụng Relationships trong Laravel

Cách sử dụng Relationships trong Laravel

Cách dùng Encryption và decryption trong Laravel

Cách dùng Encryption và decryption trong Laravel

Cách sử dụng Error Handling trong Laravel

Cách sử dụng Error Handling trong Laravel

Cách dùng URL Generation trong Larevel

Cách dùng URL Generation trong Larevel

Cách sử dụng Email Verification trong Laravel

Cách sử dụng Email Verification trong Laravel

Facades là gì? Cách dùng Facades trong Laravel

Facades là gì? Cách dùng Facades trong Laravel

Tìm hiểu và sử dụng Service Provider trong Laravel

Tìm hiểu và sử dụng Service Provider trong Laravel

Sử dụng Service Container trong Laravel dễ dàng

Sử dụng Service Container trong Laravel dễ dàng

Cách xử lý đa ngôn ngữ trong Laravel dễ dàng

Cách xử lý đa ngôn ngữ trong Laravel dễ dàng

Cách sử dụng CQRS trong Laravel từ A đến Z đơn giản

Cách sử dụng CQRS trong Laravel từ A đến Z đơn giản

Cách dùng Event Sourcing trong Laravel

Cách dùng Event Sourcing trong Laravel

Task Scheduling là gì? Cấu hình Task Scheduling trong Laravel

Task Scheduling là gì? Cấu hình Task Scheduling trong Laravel

Cách dùng Queue trong laravel để tạo tác vụ bất đồng bộ

Cách dùng Queue trong laravel để tạo tác vụ bất đồng bộ

Cách tích hợp Vue.js vào Laravel và làm một ứng dụng căn bản

Cách tích hợp Vue.js vào Laravel và làm một ứng dụng căn bản

Cách dùng Long polling trong Laravel để cải thiện trải nghiệm

Cách dùng Long polling trong Laravel để cải thiện trải nghiệm

Cách dùng Socket.io trong Laravel để tạo ứng dụng realtime

Cách dùng Socket.io trong Laravel để tạo ứng dụng realtime

Laravel WebSockets, các bước tạo WebSockets trong Laravel

Laravel WebSockets, các bước tạo WebSockets trong Laravel

Real-time web applications là gì ? Tầm quan trọng  trong Laravel

Real-time web applications là gì ? Tầm quan trọng trong Laravel

Cách tạo Database Testing trong Laravel

Cách tạo Database Testing trong Laravel

Cách dùng Browser Testing (Laravel Dusk) trong Laravel

Cách dùng Browser Testing (Laravel Dusk) trong Laravel

Top