Laravel echo
Bài đăng này đã không được cập nhật trong 3 năm
Mở bài
Xin chào các bạn! Chắc hẳn khi sử dụng laravel bạn đã biết đến Broadcasting của laravel (hay có người gọi là laravel-echo). Broadcasting của laravel trong bài viết này mình sẽ dùng laravel-echo ở phía client và mình sẽ giới thiệu 2 cách để tạo server socket:
Và chắc hẳn các bạn khi cài đặt lần đầu sẽ gặp rất nhiều rắc rối đối với công cụ này. Có một hôm đẹp trời, bạn mình có hỏi tại sao khi sử dụng private channel của thằng laravel echo này toàn bị lỗi token mismatch nhỉ. Hay chỉ là cách làm sao lấy được api key của pusher.
Hôm nay, mình sẽ trả lời các câu hỏi đó. Nói có sách mách có project. Bây giờ chúng ta cùng cài một ứng dụng cụ thể dùng Broadcasting. Bạn sẽ từ từ hiểu ra câu trả lời thôi.
Mình sẽ cài bằng cả 2 cách laravel-echo-server hoặc dùng prusher, tất nhiên ứng dụng sẽ hoạt động ngon lành cành đào không gặp một lỗi nào .
Thân bài
Chuẩn bị laravel project
Đầu tiên các bạn phải tạo một project laravel sau đó cấu hình database file .env và chạy:
composer install
npm install
sudo chmod 777 -R bootstrap/cache storage
php artisan key:generate
php artisan migrate
php artisan make:auth
Bạn phải cấu hình vitual host cho project laravel nhé.
Bỏ command trong file config/app.php
App\Providers\BroadcastServiceProvider::class,
Sửa file view home.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-primary">
<div class="panel-heading">Chat Box</div>
<div class="panel-body" style="height: 350px; overflow-y: auto" id="content">
</div>
<div class="panel-footer">
<div class="input-group">
<input type="text" class="form-control" id="input" placeholder="Enter your message...">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="send">Send</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
Tạo sự kiện chat
php artisan make:event ChatEvent
Nội dung file ChatEvent.php
<?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 ChatEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('chat-room');
}
}
Lưu ý nhỏ:
- Event phải
implements ShouldBroadcast
thì mới Broadcast được. PrivateChannel('chat-room');
broadcast ra private channelChannel('chat-room')
broadcast ra public channel
Tạo route
Route::post('/comment', function (Illuminate\Http\Request $request) {
event(new App\Events\ChatEvent($request->get('message')));
return [
'status' => true,
];
})->name('comment');
Thêm phần xác thực user trong file routes/channels.php
Broadcast::channel('chat-room', function ($user) {
return (int) $user->id < 3;
});
Ở đây nếu user có id < 3 mới có thể chat được. Còn user có id lớn hơn hoặc bằng 3 thì không thể xác thực. Bạn hãy thử sau khi làm xong nhá.
Xong phần chuẩn bị chung cho cả 2 cách cài đặt. Bây giờ sẽ đến phần cài đặt riêng.
- Nếu bạn dùng redis, laravel-echo-server, socket.io thì làm theo Cài đặt client - server 1
- Còn khi dùng pusher thì làm theo Cài đặt client - server 2.
Cài đặt client - server 1
Nếu sử dụng server 1 (có redis) thì bạn phải cài redis.
Cài đặt thêm các gói cần thiết:
- Composer
composer require predis/predis
- Npm
Thêm các gói sau vào file
package.json
rồi chạynpm install
"dotenv": "^2.0.0",
"laravel-echo": "^1.3.0",
"laravel-echo-server": "^1.1.0",
"redis": "^2.4.2",
"socket.io": "^1.4.5",
Config Driver
Sửa file .env
BROADCAST_DRIVER=redis
Config các biến
Sửa file .env
ECHO_KEY=0e1052d6edc3db2c
ECHO_HOST=laravel-echo-test.vn
ECHO_AUTH_HOST=http:\\laravel-echo-test.vn
ECHO_AUTH_ENDPOINT="/broadcasting/auth"
ECHO_DATABASE=redis
ECHO_REDIS_HOST=127.0.0.1
ECHO_SQLITE_PATH="/database/laravel-echo-server.sqlite"
ECHO_DEV_MODE=false
ECHO_PROTOCOL=http
ECHO_PORT=9090
ECHO_SSL_CERT_PATH=
ECHO_SSL_KEY_PATH=
Thay laravel-echo-test.vn thành tên host của bạn, thay ip vào là nó không chạy đúng đâu nhé.
Bạn có thể đổi cổng tại ECHO_PORT=9090
Có thể đổi ECHO_KEY=0e1052d6edc3db2c
. Cái này giống APP_KEY của laravel đấy nó chỉ cần là 1 chuỗi bất kì thôi.
Tạo server
Tạo file server.js
ở thư mục gốc với nội dung như sau:
require("dotenv").config();
var Echo = require("laravel-echo-server");
/**
* The Laravel Echo Server options.
*/
var options = {
"appKey": process.env.ECHO_KEY,
"authHost": process.env.ECHO_AUTH_HOST,
"authEndpoint": process.env.ECHO_AUTH_ENDPOINT,
"database": process.env.ECHO_DATABASE,
"databaseConfig": {
"redis": {
"port": 6379,
"host": process.env.ECHO_REDIS_HOST
},
"sqlite": {
"databasePath": process.env.ECHO_SQLITE_PATH
}
},
"devMode": process.env.ECHO_DEV_MODE,
"host": process.env.ECHO_HOST,
"protocol": process.env.ECHO_PROTOCOL,
"port": process.env.ECHO_PORT,
"referrers": [],
"socketio": {},
"sslCertPath": process.env.ECHO_SSL_CERT_PATH,
"sslKeyPath": process.env.ECHO_SSL_KEY_PATH,
"verifyAuthPath": true,
"verifyAuthServer": true
};
/**
* Run the Laravel Echo Server.
*/
Echo.run(options);
Sửa các file script Sửa file aserts/js/bootstrap.js
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
let token = document.head.querySelector('meta[name="csrf-token"]');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': token.content
}
});
import Echo from 'laravel-echo';
window.io = require('socket.io-client');
window.Echo = new Echo({
namespace: 'App.Events',
broadcaster: 'socket.io',
host: `${window.location.hostname}:9090`
});
Mình giải thích một chút:
- namespace: 'App.Events' : Event của bạn để ở trong thư mục app\Events và có namespace là App\Events. Khi event được kích hoạt thì nó sẽ Broadcast với tên event đầy đủ có cả namespace. Mình cho namespace vào đây thì lúc lắng nghe sự kiện chỉ cần lắng nghe với tên class thôi.
- host:
${window.location.hostname}:9090
: Cái này nó sẽ lấy tên host của web kiểu như:laravel-echo-test.vn:9090
. Lúc đầu mình bảo phải tạo vitual host cho project của mình rồi đấy. Bạn không thay Ip vào được đâu. Nó sẽ bị lỗi token mismatch ngay. - lưu ý nữa là
window.io = require('socket.io-client');
chữio
phải viết thường nếu bạn lỡ tay viết thànhIo
thì nó cũng sẽ lỗi
Sửa file aserts/js/app.js
require('./bootstrap');
$('#send').on('click', function () {
let message = $('#input').val();
$('#input').val('');
if (message != '') {
$.ajax({
url: 'comment',
type: 'POST',
dataType: 'json',
data: {message: message},
});
}
});
Echo.private('chat-room')
.listen('ChatEvent', (e) => {
console.log(e);
$('#content').append(`<div class="well">${e.message}</div>`);
});
Ở phần này thì mình sẽ không giải thích nhiều vì nó quá dễ hiểu rồi. Bạn chỉ cần lưu ý thế này thôi:
Echo.private
là để lắng nghe private channelEcho.channel
để lắng nghe public channel.listen('ChatEvent', calback)
lắng nghe event. Nếu phần khởi tạo Echo mà không có namespace thì ở đây phải cho tên đầy đủ của event class (Bao gồm cả namespace).
Cuối cùng là bật server lên
node server.js
Thế là đã xong. Hãy vào trang web của mình đã tạo để cảm nhận. Hãy nhớ chạy npm run dev hoặc npm run watch nhé.
Cài đặt client - server 2
Cài đặt server 1 thật vất vả phải không nào.
Bây giờ chúng ta sẽ cùng cài đặt server 2 dùng pusher. Cái này thì sẽ dùng dịch vụ của thằng khác nên nó sẽ chạy chậm hơn là laravel-echo-server đặt tại server của mình. Đầu tiên phải vào trang chủ của pusher để đăng kí một tài khoản https://pusher.com. Bạn có thể login bằng github hay google cũng được. Miễn sao có một tài khoản pusher để sử dụng.
Dashboard của pusher có dạng thế này:
Vào your app tạo 1 app mới
Đặt tên cho app, chọn cluster ==> Create my app
Vào app đã tạo để lấy key, app_id, secret, cluster. Bạn chỉ cần bấm vào app là nó sẽ hiện ra luôn trong tab overview rồi. Bạn có thể bấm vào tab App Key
để dễ nhìn hơn:
Cài các gói cần thiết:
- Composer
"pusher/pusher-php-server": "^2.6"
- Npm
"laravel-echo": "^1.3.0",
"pusher-js": "^3.2.4",
Điền các biến tương ứng đó vào file .env
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_CLUSTER=
Cấu hình cluster trong file config/broadcasting.php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_CLUSTER'),
'encrypted' => true
],
],
Sửa file assert/js/bootstrap.js
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
let token = document.head.querySelector('meta[name="csrf-token"]');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': token.content
}
});
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Echo = new Echo({
namespace: 'App.Events',
broadcaster: 'pusher',
key: '11f716410294b4f3***',
cluster: 'ap1',
encrypted: true
});
Thay key
và cluster
bên trên bằng key
và cluster
của bạn
File aserts/js/app.js giống với file của server 1
require('./bootstrap');
$('#send').on('click', function () {
let message = $('#input').val();
$('#input').val('');
if (message != '') {
$.ajax({
url: 'comment',
type: 'POST',
dataType: 'json',
data: {message: message},
});
}
});
Echo.private('chat-room')
.listen('ChatEvent', (e) => {
$('#content').append(`<div class="well">${e.message}</div>`);
});
Xong rồi bạn chạy npm run dev hoặc npm run watch và vào trang của mình để hưởng thụ thành quả.
Cấu hình pusher thật đơn giản phải không
Kết luận
Qua bài viết này mình đã cùng với các bạn cài đặt và sử dụng thành công broadcast của laravel. Hi vọng sẽ giúp ích được cho các bạn.
Nếu có bất cứ câu hỏi hay khó khăn gì hãy comment bên dưới.
Nếu thấy bài viết hay thì hãy upvote và chia sẻ cho mọi người nhé.
All rights reserved