For Laravel Websocket Integration Step By Step
Install Laravel Websocket Packages
Official site : Laravel Websocket
Step 1 Command : composer require beyondcode/laravel-websockets |
Facing Issue Some time using above command laravel-websocket not install so you can write below
Command
Command : composer require beyondcode/laravel-websockets -w
Get Reference : Link
Step 2
Command : php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations" |
Step 3
Command : php artisan migrate |
Step 4 You need to publish the WebSocket configuration file:
Command : php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config" |
2) Install Pusher
Step 1 : Command : composer require pusher/pusher-php-server |
Step2 : Open your .env and Change Below things If you using http then change below thing in env Http BROADCAST_DRIVER=pusher
PUSHER_APP_ID=anyappid PUSHER_APP_KEY=anyappkey PUSHER_APP_SECRET=anyappsecret PUSHER_HOST= PUSHER_PORT= PUSHER_SCHEME= PUSHER_APP_CLUSTER=mt1 REDIS_PREFIX= LARAVEL_WEBSOCKETS_PORT=6001 If you are using https then change below thing in .env Https BROADCAST_DRIVER=pusher
PUSHER_APP_ID=anyappid PUSHER_APP_KEY=anyappkey PUSHER_APP_SECRET=anyappsecret PUSHER_HOST= PUSHER_PORT= PUSHER_SCHEME= PUSHER_APP_CLUSTER=mt1 REDIS_PREFIX= //for this parameter added if are using https give you ssl certificate path LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT = /var/www/html/b_laravel/ssl_cert/apache-selfsigned.pem LARAVEL_WEBSOCKETS_SSL_LOCAL_PK = /var/www/html/b_laravel/ssl_cert/apache-selfsigned-key.pem LARAVEL_WEBSOCKETS_SSL_PASSPHRASE = "" LARAVEL_WEBSOCKETS_PORT=6001 |
Step 3 :
config/broadcasting.php
In this if Two way Setup if you are using http then socket work on ws and if you are using https Wss
1)If You are using Http then below change in your config/broadcasting.php file
Reference site :link
'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' ], ],
2)If You are using Https then below change in your config/broadcasting.php file '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'), 'host' => '127.0.0.1', 'encrypted' => true, 'port' => 6001, 'scheme' => 'https', 'debug' => true, 'useTLS' => true, 'curl_options' => [ CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_SSL_VERIFYPEER => 0, ] ],
'client_options' => [ 'verify' => false, // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html ],
3) Change in config/websockets.php
1)If You are using Http then below change in your config/websockets.php file 'apps' => [ [ 'id' => env('PUSHER_APP_ID'), 'name' => env('APP_NAME'), 'key' => env('PUSHER_APP_KEY'), 'secret' => env('PUSHER_APP_SECRET'), 'path' => env('PUSHER_APP_PATH'), 'capacity' => null, 'enable_client_messages' => false, 'enable_statistics' => true, ],
1)If You are using Https then below change in your config/websockets.php file 'apps' => [ [ 'id' => env('PUSHER_APP_ID'), 'name' => env('APP_NAME'), 'key' => env('PUSHER_APP_KEY'), 'secret' => env('PUSHER_APP_SECRET'), 'path' => env('PUSHER_APP_PATH'), 'capacity' => null, 'enable_client_messages' => false, 'enable_statistics' => true, ], |
In ssl part you have to add below three parameter 1)verify_peer 2)verify_peer_name 3)allow_self_signed
'ssl' => [ /* * Path to local certificate file on filesystem. It must be a PEM encoded file which * contains your certificate and private key. It can optionally contain the * certificate chain of issuers. The private key also may be contained * in a separate file specified by local_pk. */ 'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
/* * Path to local private key file on filesystem in case of separate files for * certificate (local_cert) and private key. */ 'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
/* * Passphrase for your local_cert file. */ 'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true, ], |
4)routes/web.php Add this line Route::post('/broadcasting/auth', function () { return Auth::user(); }); |
5)config/app.php
In order to turn on broadcasting for any Laravel application, we need to go to config/app.php and uncomment:
App\Providers\BroadcastServiceProvider::class, |
3) Install Laravel Echo and Pusher.js
Command : npm install --save laravel-echo pusher-js
Step1 : Change in resources/js/bootstrap.js
import axios from 'axios'; window.axios = axios;
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) { window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content; } else { console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token'); }
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/** * Echo exposes an expressive API for subscribing to channels and listening * for events that are broadcast by Laravel. Echo and event broadcasting * allows your team to easily build robust real-time web applications. */
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher; //console.log(window.location.hostname); window.Echo = new Echo({ broadcaster: 'pusher', key: 'anyappkey', cluster: 'mt1', wsHost: window.location.hostname, wsPort: 6001, wssPort: 6001, forceTLS: true, disableStats: true, });
If you are using http then you to connect using below code window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'pusher', key: 'anyappkey', cluster: 'mt1', wsHost: window.location.hostname, wsPort: 6001, wssPort: 6001, forceTLS: false, disableStats: true, });
wsPort and wssPort port you can change with your requirement |
4)Install supervisord
Command : sudo apt install supervisor
How config Supervisor in ubuntu system
1) Go to : cd /etc/supervisor/conf.d/
Create file websockets.conf using sudo nao websockets.conf
Write below details
Change your laravel project path : /var/www/html/b_laravel/artisan
[program:websockets]
command=/usr/bin/php /var/www/html/b_laravel/artisan websockets:serve
numprocs=1
autostart=true
autorestart=true
user=root
4)sudo service supervisor restart
5)check status your websocket : sudo service supervisor status
5)How to setup virtual host in nginx for https
Official website : Link
Need to add only this thing
map $http_upgrade $type { default "web"; websocket "ws"; }
location @web { try_files $uri $uri/ /index.php?$query_string; } location @ws { proxy_pass http://127.0.0.1:6001; proxy_set_header Host $host; proxy_read_timeout 60; proxy_connect_timeout 60; proxy_redirect off;
# Allow the use of websockets proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } |
6)How to setup virtual host in apache2 for https
Add this proxy pass parameter in you apache2 also check that in you apache proxy pass enable or not
Please check in this site : Link
Fire below command
sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_balancer sudo a2enmod lbmethod_byrequests
sudo systemctl restart apache2 |
SSLEngine on
SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key
ProxyPass /ws ws://localhost:6001/ ProxyPassReverse /ws ws://localhost:6001/ |
Note : When anything Change Then Please restart the supervisor. If you have not use
We supervisor then you have to restart websocket
1)if you use supervisor restart : sudo service supervisor restart
2)if you use websocket direct : php artisan websockets:restart
You have clean websocket log using scheduler and manually command also
php artisan websockets:clean
Link
//app/Console/Kernel.php
protected function schedule(Schedule $schedule) { $schedule->command('websockets:clean')->daily(); } |
7)Laravel WebSocket Example step by step
1)Create ChatController php artisan make:controller ChatController |
2)import app.js and app.css if not in global level For reference : https://stackoverflow.com/questions/73331352/how-import-own-js-file-into-vite @vite(["resources/css/app.css","resources/js/app.js"]) |
3)fire command : npm run build |
4)Create Event Using below Command Command : php artisan make:event NewMessage |
Below Change you have to do
<?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 ChatEvent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $somedata; /** * Create a new event instance. */ public function __construct($somedata) { $this->somedata = $somedata; }
/** * Get the channels the event should broadcast on. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): Channel { return new Channel('ChatMessageChannel'); } } |
1)class ChatEvent to class ChatEvent implements ShouldBroadcast
2)create : public $somedata;
3)__construct method pass $somedata and assing $this->somedata = $somedata;
public function __construct($somedata)
{
$this->somedata = $somedata;
}
4)
- Change public function broadcastOn(): Array to public function broadcastOn(): Channel
- return [ new PrivateChannel('channel-name'),]; to return new Channel('ChatMessageChannel');
public function broadcastOn(): Channel
{
return new Channel('ChatMessageChannel');
}
5)routes/channels.php
Add This
Broadcast::channel('ChatMessageChannel', function ($user) { return true; }); |
6)routes/web.php
<?php
use Illuminate\Support\Facades\Route; use App\Http\Controllers\ChatController; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider and all of them will | be assigned to the "web" middleware group. Make something great! | */
Route::get('/', function () { return view('welcome'); }); Route::get('chat', [ChatController::class, 'index'])->name('chat'); Route::Post('sendmessage', [ChatController::class, 'sendmessage'])->name('sendmessage'); Route::get('broadcastmessage', [ChatController::class, 'getmessage'])->name('broadcastmessage'); Route::post('/broadcasting/auth', function () { return Auth::user(); }); |
1)in this three method need to add
1)Route::get('chat', [ChatController::class, 'index'])->name('chat');
-For Message Send UI
2)Route::Post('sendmessage', [ChatController::class, 'sendmessage'])->name('sendmessage');
-For Message Send
3)Route::get('broadcastmessage', [ChatController::class, 'getmessage'])->name('broadcastmessage');
-for received socket message
7)app/Http/Controllers/ChatController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Support\Facades\Redirect; use Pusher\Pusher; class ChatController extends Controller { public function index() { return view('chat'); } public function sendmessage(Request $request) { //dd($request->all()); $sendData['name'] = $request->your_name; $sendData['message'] = $request->send_meesage; $paramater['chanel'] = "guest_user"; $paramater['event'] = "ChatEvent"; $paramater['data'] = $sendData; try { $pusher = new Pusher( config('broadcasting.connections.pusher.key'), config('broadcasting.connections.pusher.secret'), config('broadcasting.connections.pusher.app_id'), config('broadcasting.connections.pusher.options', []), new \GuzzleHttp\Client(['verify' => false]), ); $pusher->trigger($paramater['chanel'], $paramater['event'], $paramater['data']); } catch (Exception $e) { // Handle Pusher API error // You might log the error, notify administrators, or respond to the client accordingly dd($e->getMessage()); } return Redirect::to('/chat')->with(['type' => 'success','message' => 'Your message sent sucessfully']); } public function getmessage() { return view('get_message'); } } |
1)In controller first you have to add two namespace
1) use Illuminate\Support\Facades\Redirect;
-for redirect
2) use Pusher\Pusher;
--for pusher message send
2)
public function index()
{
return view('chat');
}
-in this i have added for ui Message sent
3)function sendmessage
- for pusher throw send message you have to manage
1)channel - which channel you have to send data
2)event - which event you have to pass data throw
3)data - you have to pass data to create array
-
$pusher = new Pusher( config('broadcasting.connections.pusher.key'), config('broadcasting.connections.pusher.secret'), config('broadcasting.connections.pusher.app_id'), config('broadcasting.connections.pusher.options', []), new \GuzzleHttp\Client(['verify' => false]), ); |
-this code for configure pusher message in this new \GuzzleHttp\Client(['verify' => false]),
this option we have to pass when we have use self signed certificate or our ssl not working then
we have to use this option
-
$pusher->trigger($paramater['chanel'], $paramater['event'], $paramater['data']);
-this line triggers data for a particular channel.
4)getmessage
- in this blade file we have to listen particular channel
8) send message ui blade file : resources/views/chat.blade.php
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts --> <link rel="preconnect" href="https://fonts.bunny.net"> <link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" /> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-1.12.4.js" integrity="sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU=" crossorigin="anonymous"></script> @vite(["resources/css/app.css","resources/js/app.js"]) <meta name="csrf-token" content="{{ csrf_token() }}"> </head> <body class="antialiased"> <div class="container"> <form method="post" action="{{route('sendmessage')}}"> <div class="form-group"> <label for="your_name">Your Name</label> <input type="text" class="form-control" id="your_name" name="your_name"> </div> <div class="form-group mb-2"> <label for="send_meesage">Your Message</label> <textarea id="send_meesage" name="send_meesage" class="form-control" ></textarea> </div> <input type="hidden" name="_token" id="csrf-token" value="{{ Session::token() }}" /> <button type="submit" class="btn btn-primary">Send</button> </form> </div> </body> </html> |
9) get message ui blade file : resources/views/get_message.blade.php
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts --> <link rel="preconnect" href="https://fonts.bunny.net"> <link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" /> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-1.12.4.js" integrity="sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU=" crossorigin="anonymous"></script> @vite(["resources/css/app.css","resources/js/app.js"]) <meta name="csrf-token" content="{{ csrf_token() }}"> </head> <body class="antialiased"> <div class="container"> <div class="row" > <div class="col-4"></div> <div class="col-4"> <label>User Name </label> <span style="color: red" id="user_name"></span> <br/> <label>MessageSend By User </label> <span style="color: red" id="send_user_msg"></span> </div> <div class="col-4"></div> </div> </div> <script type="text/javascript"> var chanelName = "guest_user" $(window).on('load', function () { var checkEcho = window.Echo; if (typeof checkEcho !== "undefined") { window.Echo.channel(chanelName) .listen('.ChatEvent', (e) => { alert('socket Send Message Please read on Screen') $("#user_name").html(e.name); $("#send_user_msg").html(e.message); }); } }); </script> </body> </html> |
1)in this we have listen particular chanel which send data from socket
var chanelName = "guest_user" $(window).on('load', function () { var checkEcho = window.Echo; if (typeof checkEcho !== "undefined") { window.Echo.channel(chanelName) .listen('.ChatEvent', (e) => { alert('socket Send Message Please read on Screen') $("#user_name").html(e.name); $("#send_user_msg").html(e.message); }); } }); |
- i have pass data in guest_user so i have listen this channel using laravel echo
10)below Url
1){Domain Name}/chat
2){Domain Name}/broadcastmessage - this is open different tab or browser when you can get message form pusher you can get alert here and message
3){Domain Name}/laravel-websockets - this graph which you to change socket connect or not
[program:websockets] command=/usr/bin/php /var/www/html/b_laravel/artisan websockets:serve numprocs=1 autostart=true autorestart=true user=root |
The book's background is more attention-grabbing than the textual content. Please consider doing a redesign and adding code highlights if possible.
ReplyDeleteLive savin, thank you very much!
ReplyDelete