Broadcasting with laravel echo
Bài đăng này đã không được cập nhật trong 7 năm
Giới thiệu
Như các bạn đã biết, ngày nay với việc ứng dụng websocket vào website sẽ khiến trang web trở nên linh động hơn, cải thiện các chức năng cũng như tương tác với người dùng tốt hơn. Vì vậy websocket ngày càng trở nên quang trọng đối với việc phát triển một website. Và sau đây mình xin giới thiệu về boardcasting trong laravel hỗ trợ cho việc tích hợp websocket vào trang web của các bạn
Cài đặt
Đầu tiên bạn phải cài đặt các gói thư viện thông qua npm
"redis": "^2.7.1",
"socket.io": "^2.0.3",
"socket.io-client": "^1.7.1",
"dotenv": "^2.0.0",
"laravel-echo": "^1.3.0",
"laravel-echo-server": "^1.1.0"
Sau đó các bạn chạy npm install
để cài đặt các gói này.
Cài đặt redis thông qua composer composer require predis/predis
Config
config file .env
BROADCAST_DRIVER=redis
...
ECHO_KEY=9te930q989itok355krkfrs95j92ais01iim3i5sjs1k93g87kt8qdd0ur91
ECHO_HOST=mt.dev
ECHO_AUTH_HOST=http:\\mt.dev
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=true
ECHO_PROTOCOL=http
ECHO_PORT=9090
ECHO_SSL_CERT_PATH=
ECHO_SSL_KEY_PATH=
config config/app.php
các bạn mở comment dòng App\Providers\BroadcastServiceProvider::class,
ở mục providers
và thêm vào mục aliases
'LRedis' => Illuminate\Support\Facades\Redis::class,
Tạo server
Các bạn chạy lệnh php artisan make:auth
để laravel tự sinh các phần để login và authentication nhé.
Ở đây, mình sẽ giải thích các luồng dữ liệu.
Đầu tiên mình sẽ tạo 1 event chat để lắng nghe sự kiện. Event phải implements ShouldBroadcast
<?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;
private $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');
}
// phương thức này định nghĩa dữ liệu sẽ được gửi qua sự kiện của event chat
public function broadcastWith()
{
return [
'message' => $this->message,
'user' => auth()->user(),
];
}
}
Sau đó mình tạo một controller để gọi event chat php artisan make:controller ChatController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Events\ChatEvent;
use LRedis;
class ChatController extends Controller
{
private $redis;
public function __construct()
{
$this->redis = LRedis::connection();
}
protected function chat(Request $request)
{
if (!$request->ajax()) {
return ['status' => false];
}
event(new ChatEvent($request->get('message')));
return ['status' => true];
}
}
Tạo các router tương ứng
Route::post('/chat', 'Common\ChatController@chat')->name('chat');
Route::get('/get-chat', function () {
return view('chat.chat');
});
Các bạn thêm vào file channels.php
một như sau
Broadcast::channel('chat-room', function ($user) {
// athorization for user can listener event
return true; // all user can chat
});
Ở đây, file channels.php này sẽ xác thực những user nào được phép join vào kênh chat-room cũng như được lắng nghe hay tạo sự kiện trên đó.
Tạo file server.js theo đường dẫn Node/server.js
require("dotenv").config({ path: '../.env' })
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)
tiếp theo mình sẽ tạo view chat box chat/chat.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
Sữa lại file bootstrap.js trong assests
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`
})
Tạo 1 file js có tên chat.js
import Echo from 'laravel-echo'
let echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':9090'
})
$('#send').on('click', function () {
let message = $('#input').val()
$('#input').val('')
if (message != '') {
$.post('chat' , { message: message })
}
})
echo.private('chat-room')
.listen('ChatEvent', (e) => {
$('#content').append(`<div class="well">${ e.user.name + ': ' + e.message }</div>`)
})
cuối cùng là biên dịch file js
mix.js('resources/assets/js/app.js', 'public/js')
.js('resources/assets/js/chat.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
Và đừng quên khai báo <script src="{{ asset('js/chat.js') }}"></script>
vào file layout/app.blade.php
Cuối cùng bạn chạy lệnh node Node/server.js
Giải thích
Khi bạn nhấn nút send thì chúng ta sẽ thực hiện một phương thức post lên server với controller chatevent. Sau khi gọi phương thức chat chúng ta sẽ khởi tạo một event với dữ liệu truyền qua là message chúng ta gửi đến. Và trong event Chat với phương thức broadcastWith sẽ định nghĩa dữ liệu được truyền qua server node. Đến đây, việc còn lại là ở client, laravel echo sẽ lắng nghe sự kiện ở channel với class name tương ứng . Chúc các bạn code vui vẻ . nguồn tham khảo : https://laravel.com/docs/5.5/broadcasting
All rights reserved