Nowadays, many advanced applications require real-time communication. Laravel has many inbuilt features to cover up the latest technologies and easy implementation. Laravel supports pusher, Redis, and socket.io to develop web socket interfaces.
I'm going to discuss how to set up a web socket communication channel using a self-hosted pusher, laravel echo, and laravel web socket. Using this tutorial, you would be able to configure the setup for your own chat application.
I've divided this tutorial into three steps,
- Server-side setup
- Client-side setup
- Final Execution - Create Broadcast Event & Listen to channel
Server-Side Setup
Step 1
If you're using broadcasting events, you should install a pusher package. Laravel - version 5.3 and above has built-in support for Pusher Channels as a Broadcasting backend.
composer require pusher/pusher-php-server "~4.0"
Pusher Compatible Laravel Websockets
The laravel-websockets is a pure PHP, Pusher compatible WebSocket package for Laravel. This package allows you to leverage the full power of Laravel broadcasting without an external WebSocket provider or Node. For more information on installing and using this package, please consult its official documentation.
composer require beyondcode/laravel-websockets
Change in .env
BROADCAST_DRIVER=pusher
APP_URL=http://127.0.0.1:8000
you should add the host and port configuration key to your config/broadcasting.php and add it to the pusher section. The default port of the Laravel WebSocket server is 6001.
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http'
],
],
Run Webocket & Test
php artisan websocket:server
Open this URL : http://127.0.0.1:8000/laravel-websockets
Step 2
We use laravel broadcaster service, Let's uncomment following line from config/app.php
App\Providers\BroadcastServiceProvider::class
Step 3
By installing pusher package in step 1, We get a new configuration file in the config folder, Let's configure 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_APP_CLUSTER'),
'useTLS' => true,
],
],
Step 4
As we are not using pusher.com, It's time to change some dummy value in .env. The values shown below are just demoed purposes. It would be more realistic values on production. Why do we want to set dummy values here? You remember in step1 we install the pusher package that enables pusher on hour host, We're using the pusher broadcast driver supported by laravel so let's configure default environment variables.
PUSHER_APP_ID=123456
PUSHER_APP_KEY=scvbmzkmvc
PUSHER_APP_SECRET=xcnmcxdfgvc
PUSHER_APP_CLUSTER=mt1
BROADCAST_DRIVER=pusher
QUEUE_CONNECTION=sync
Step 5
Don't forget to check csrf tag in app.blade.php. Channel authentication will need csrf-token.
<meta name="csrf-token" content="{{ csrf_token() }}">
Configuration on Client Side
We're going to add client-side code that enables communication from HTTP to a socket server using laravel echo
Step 1
You need client-side pusher js library that supports web browsers, web workers, Node.js and React Native.
npm install - save pusher-js
Step 2
Laravel Echo is a JavaScript library that makes it painless to subscribe to channels and listen for events broadcast by Laravel.
npm install - save laravel-echo pusher-js
Step 3
Comment Vue.js in resources/js/app.js, if you're not using it.
Step 4
Remove comment from resources/js/bootstrap.js and add Hosts
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
forceTLS: true,
wsHost: window.location.hostname,
wsPort: 6001
});
Your laravel-echo-server.json should look like this,
{
"authHost": "http://127.0.0.1:8000",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "626725232e738e727",
"key": "4ac7dd96bc51f1f345344381230f2644737d"
}
],
"database": "redis",
"databaseConfig": {
"redis": {
"port": "6379",
"host": "127.0.0.1",
"keyPrefix": ""
}
},
"devMode": true,
"host": null,
"port": "8081",
"protocol": "http",
"socketio": {},
"secureOptions": 67108864,
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "http://localhost:80",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
Step 5
Compile client-side js and get ready!!!
Run - npm run dev
Final Execution - Create Broadcast Event & Listen to channel
Step 1 - Create Event
Create TestEvent.php in App/Events
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class TestEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public $count;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
$this->message = 'hello';
$this->count = 1;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn(){
return new Channel('test');
}
public function broadcastWith(){
return ['message' => str_random(15)];
}
}
Step 2- Listen channel in App.blade.php
<script src="{{ asset('/js/app.js') }}"></script>
<script>
Echo.channel('private-test')
.listen('TestEvent', (e) => {
console.log(e);
})
</script>
Verify CSRF token once again!! Server-side setup - Step 5
Execution
1. Start laravel echo server
laravel-echo-server start
2. Start websocket server
php artisan websocket:server
php artisan queue:work
3. Recompile app.js
npm run dev
4. Fire an event using php tinker, you should have a console log in the browser.
php artisan tinker
event(new \App\Events\TestEvent());
Conclusion
We've implemented a basic setup of all components required to listen to the channel for real-time communication. We've seen how to set up a web socket with help of a pusher library using laravel broadcasting on the self-host.
Top comments (9)
Why you need laravel-echo-server here? I don't think it necessary here.
Currently, the Pusher information now required and beyondcode/laravel-websockets now require real pusher tokens. I don't know why.
This tutorial was good in the start but it has left so many questions unanswered in the end. I think that you just copied most of the things from a different blog where laravel-echo-server was being used.
-1
This was documented by me at the time when I configured everything step by step. I thought to share my steps with community. Let me know what kind of questions you have. I'll try to make this article useful with more information. I used pusher intially, and then moved to Redis
Please your broadcastOn channel is 'test' but instead in Echo you listen instead to 'private-test'
Why ?
Why do you use queue:work?
That depends on the method you follow.
Let say, QUEUE_CONNECTION=database and When you fire an event "event(new \App\Events\TestEvent());" Those events drop in a database queue. We need queue:work at that time.
Generally, Queues are recommended that prevents block on the frontend.
can you show, whats config in file laravel-echo-server.json, because i think your topic is missed information when run laravel-echo-server start
I've added sample laravel-echo-server.json in the article.
Where is stored the file laravel-echo-server.json?