Xin chào các bạn, tuần này mình sẽ viết một bài về cách xử lý Real Time(thời gian thực) với Laravel và Pusher, sau bài này các bạn có thể hiểu được cái base cơ bản và sau đó phát triển tiếp lên như là viết chức năng bình luận hay là chức năng chat real time…..v..v.
Những nội dung có trong bài này:
- Giới thiệu về Pusher và Laravel
- Cấu hình Laravel kết nối với Pusher
- Tạo một App trên Pusher
- Cài đặt Laravel, config tới Pusher App vừa tạo.
- Viết code xử lý real time
- Code Events
- Code Route & Controller
- Code View
1 – Giới thiệu về Pusher và Laravel
Về Laravel thì mình sẽ không nói nhiều trong bài này, vì nó là một Framework lập trình web khá nổi tiếng, bạn nào chưa biết thì có thể xem qua bài này:
Còn về Pusher, có thể nói nó là một dịch vụ bên thứ 3 mà cung cấp cho người dùng một server ảo làm trung gian để xử lý các dữ liệu được yêu cầu trong thời gian thực.
Pusher xử lý thời gian thực thông qua cơ chế hỗ trợ giao tiếp 2 chiều WebSockets tới ứng dụng web, điện thoại di động hoặc bất kỳ thiết bị kết nối Internet nào khác. Xem thêm tại đây: https://pusher.com/docs
2 – Cấu hình Laravel kết nối đến Pusher
Việc đầu tiên chúng ta cần là đăng ký một tài khoản trên Pusher, cái này nhanh thôi, đăng ký bằng G+ hay Github đều được cả.
– Sau khi đăng ký, các bạn tạo một ứng dụng mới, lưu ý mình ở Việt Nam thì chọn location ap1(Singapore) để có tốc độ truy cập nhanh nhất nhé.
– Tạo xong app, bạn tích sang tab App Keys và để ý mấy thông tin app_id, key, secret, cluster, lát nữa chúng ta sẽ dùng những thông số này để cấu hình trong project Laravel.
Bước tiếp theo ta cần là tạo project Laravel và cấu hình với App vừa tạo. Làm lần lượt các bước dưới đây:
– Tạo một project Laravel mới thông qua Composer, phiên bản hiện tại mình sử dụng là Laravel 5.4:
composer create-project --prefer-dist laravel/laravel demo-real-time-app
– Cài đặt gói thư viện Pusher PHP:
composer require pusher/pusher-php-server
– Cài đặt Javascript dependencies:
npm install
– Cài đặt 2 thư viện javascript cần thiết cho việc xử lý sự kiện thời gian thực đó là Laravel Echo và Pusher JS:
npm install --save laravel-echo pusher-js
– Mở file .env trong project Laravel, kéo xuống cuối cùng, chúng ta dùng những thông tin trong App Keys ở trên để cấu hình trong này:
PUSHER_APP_ID=YOUR_APP_ID PUSHER_APP_KEY=YOUR_APP_KEY PUSHER_APP_SECRET=YOUR_APP_SECRET
– Và cũng trong file .env sửa dòng BROADCAST_DRIVER=log thành BROADCAST_DRIVER=pusher
BROADCAST_DRIVER=pusher
– Tiếp tục mở file config/app.php, tìm đến dòng App\Providers\BroadcastServiceProvider::class, dòng này ban đầu đang được comment lại, chúng ta bỏ comment nó đi để có thể làm việc được với Broadcast.
– Sau đó kéo xuống dưới và thêm dòng sau vào cuối mảng aliases:
'Pusher' => Pusher\Pusher::class,
– Mở file config/broadcasting.php, thêm 2 dòng dưới đây vào option array trong mục cấu hình pusher để xác định location và mã hóa dữ liệu trên đường truyền:
'cluster' => 'ap1', 'encrypted' => true
– Bước cấu hình cuối cùng, bạn mở file bootstrap.js trong thư mục resources/assets/js/, kéo xuống dưới cùng và bỏ comment đoạn code dưới đây, đồng thời điền pusher-app-key của bạn vào:
3 – Viết code xử lý real time
– Code Event:
Đầu tiên, chúng ta cần tạo một event mới, mình ví dụ tạo một event có tên là DemoPusherEvent:
php artisan make:event DemoPusherEvent
Khi đó, một file DemoPusherEvent.php được tạo trong thư mục app/Events, mình sẽ viết code cho nó như sau:
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Queue\SerializesModels; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class DemoPusherEvent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; /** * Create a new event instance. * * @return void */ public $message; public function __construct($message) { $this->message = $message; } /** * Get the channels the event should broadcast on. * * @return Channel|array */ public function broadcastOn() { return new Channel('channel-demo-real-time'); } }
Lưu ý là chúng ta phải implements ShouldBroadcast để có thể sử dụng được Event Broadcasting và trong function broadcastOn() ta sử dụng Chanel thay vì PrivateChanel.
Khi sự kiện DemoPusherEvent ở trên được chạy, một message trong hàm khởi tạo __construct của chúng ta sẽ được truyền lên server Pusher thông qua một kênh chung có tên là chanel-demo-real-time, bạn có thể đặt tên cho kênh này tùy ý.
– Code Route & Controller
Bạn vào file routes/web.php và thêm 2 route này vào:
<?php // gọi ra trang view demo-pusher.blade.php Route::get('demo-pusher','FrontEndController@getPusher'); // Truyển message lên server Pusher Route::get('fire-event','FrontEndController@fireEvent');
Tạo file controller FrontEndController.php:
php artisan make:controller FrontEndController
Nội dung file FrontEndController.php như sau:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Events\DemoPusherEvent; class FrontEndController extends Controller { public function getPusher(){ // gọi ra trang view demo-pusher.blade.php return view("demo-pusher"); } public function fireEvent(){ // Truyền message lên server Pusher event(new DemoPusherEvent("Hi, I'm Trung Quân. Thanks for reading my article!")); return "Message has been sent."; } }
– Code View
Sau khi đã có route và controller, mình sẽ tạo một file demo-pusher.blade.php trong thư mục resources/views/ để hiển thị nội dung của message trong thời gian thực.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Demo Pusher - Trung Quân</title> <link rel="shortcut icon" href="{{ asset('images/favicon/logo-trungquandev.png') }}" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <style type="text/css" media="screen"> #messages{ color: #1abc9c; } #messages li{ max-width: 50%; margin-bottom:10px; border-color: #34495e; } </style> </head> <body> <div class="container"> <div class="content"> <h1>Laravel & Pusher: Demo real-time web application.</h1> <small> Author: <a href="https://trungquandev.com/" target="__blank">https://trungquandev.com/</a> </small><br><br> <p>Message preview:</p> <ul id="messages" class="list-group"></ul> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://js.pusher.com/4.1/pusher.min.js"></script> <script> $(document).ready(function(){ // Khởi tạo một đối tượng Pusher với app_key var pusher = new Pusher('YOUR_PUSHER_APP_KEY', { cluster: 'ap1', encrypted: true }); //Đăng ký với kênh chanel-demo-real-time mà ta đã tạo trong file DemoPusherEvent.php var channel = pusher.subscribe('channel-demo-real-time'); //Bind một function addMesagePusher với sự kiện DemoPusherEvent channel.bind('App\\Events\\DemoPusherEvent', addMessageDemo); }); //function add message function addMessageDemo(data) { var liTag = $("<li class='list-group-item'></li>"); liTag.html(data.message); $('#messages').append(liTag); } </script> </body> </html>
Mấu chốt của việc hiển thị dữ liệu thời gian thực ra view là đoạn javascript ở trên.
Đầu tiên ta khởi tạo một đối tượng pusher với app_key, rồi đăng ký đối tượng pusher đó với kênh mà ta đã tạo trong DemoPusherEvent.
Cuối cùng là bind (đính kèm xử lý sự kiện DemoPusherEvent với function addMessageDemo, function này sẽ lấy nội dung message từ server Pusher và hiển thị ra trình duyệt tùy theo cách bạn định nghĩa.
Vậy là đã xong rồi đấy, bây giờ bạn hãy ra trình duyệt chạy route demo-pusher sẽ thấy như sau:
Hiện tại ở Message preview chưa có gì, bạn tiếp tục chạy route fire-event ở một trình duyệt khác hoặc bật trình duyệt ẩn danh lên rồi chạy.
Xong, quay lại tab demo-pusher vừa nãy bạn sẽ thấy nội dung message đã xuất hiện mà không cần phải load lại trang.
Bạn cũng có thể xem nội dung message trên server Pusher, tại app của bạn, click sang tab Debug Console:
Như vậy mình đã demo xong một ví dụ đơn giản, từ ví dụ này, các bạn có thể tự phát triển vào project của mình những ý tưởng khác nhau, như là chức năng bình luận thời gian thực, chat real time…vv..
Cảm ơn các bạn đã xem bài viết của mình !!!
Best Regards – Trung Quân – Green Cat