Digging Deep
Laravel Driver
This package allows the usage of Conveyor as a broadcasting driver in Laravel. Here is the repo: (https://github.com/kanata-php/conveyor-laravel-broadcaster).
To understand how to broadcast with Laravel, visit Broadcasting.
Quick Start
Table of Contents
- Step 1: Install the package via composer
- Step 2: Publish the configuration
- Step 3: Add Service Provider
- Step 4: Enable Laravel broadcasting
- Step 5: Add broadcasting config
- Step 6: Protect your channels
- Step 7: Create a user for authorization - if needed
- Step 8: Migrate the database
- Step 9: Install the Conveyor JS Client
- Extra: Simple Conveyor Server for this example
Step 1: Install the package via composer
1composer require kanata-php/conveyor-laravel-broadcaster
Step 2: Publish the configuration
1php artisan vendor:publish --provider="Kanata\LaravelBroadcaster\ConveyorServiceProvider"
Step 3: Add Service Provider
Laravel 10 backwards:
1<?php
2return [
3 // ...
4 'providers' => [
5 // ...
6 Kanata\LaravelBroadcaster\ConveyorServiceProvider::class,
7 ],
8 // ...
9];
Laravel 11 onwards:
1<?php
2
3return [
4 // ...
5 Kanata\LaravelBroadcaster\ConveyorServiceProvider::class,
6];
Step 4: Enable Laravel broadcasting
This is for Laravel 11 and forward, if in any other version just skip this step!
1php artisan install:broadcasting
Step 5: Add broadcasting config
Add the following to your config/broadcasting.php
file:
1<?php
2
3return [
4 // ...
5 'conveyor' => [
6 'driver' => 'conveyor',
7 'protocol' => env('CONVEYOR_PROTOCOL', 'ws'),
8 'host' => env('CONVEYOR_URI', 'localhost'),
9 'port' => env('CONVEYOR_PORT', 8181),
10 ],
11];
Step 6: Protect your channels
1use App\Models\User;
2use Illuminate\Support\Facades\Broadcast;
3
4Broadcast::channel('actions-channel', function (User $user) {
5 return true; // we are authorizing any user here - update according to your needs!
6});
Step 7: Create a user for authorization - if needed
1php artisan tinker
Within tinker, you can create a user:
1App\Models\User::factory()->create(['email' => '[email protected]', 'password' => Hash::make('password')]);
Step 8: Migrate the database
Set the configurations for the WebSocket server in the .env
file:
1# ...
2BROADCAST_CONNECTION=conveyor
3# ...
4CONVEYOR_DATABASE=pgsql
5JACKED_SERVER_WEBSOCKET_ENABLED=true
6# ...
CONVEYOR_DATABASE
is optional and defaults to mysql.
Then run migrations:
1php artisan migrate
Step 9: Install the Conveyor JS Client:
1npm install socket-conveyor-client
Important: Don't forget to run
npm run build
!
Add this to the bootstrap.js file of your Laravel app so the Conveyor client is available globally:
1import Conveyor from "socket-conveyor-client";
2
3window.Conveyor = Conveyor;
Remember to run npm install
and npm run dev
or npm run prod
to compile the assets.
Info: If you want to send one-off messages to the Conveyor WebSocket server, you can just dispatch an event like follows:
1<?php 2 3namespace App\Events; 4 5use Illuminate\Broadcasting\InteractsWithBroadcasting; 6use Illuminate\Broadcasting\PrivateChannel; 7use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; 8 9class TestEvent implements ShouldBroadcastNow 10{ 11 use InteractsWithBroadcasting; 12 13 public function __construct( 14 public string $message, 15 public string $channel, 16 ) { 17 $this->broadcastVia('conveyor'); 18 } 19 20 public function broadcastOn(): array 21 { 22 return [ 23 new PrivateChannel($this->channel), 24 ]; 25 } 26}
1event(new App\Events\TestEvent( message: 'my message', channel: 'my-channel'));
Important: notice that we are using
ShouldBroadcastNow
instead ofShouldBroadcast
. Conveyor doesn't need queueing and is much faster this way. If you want, you can still use queues.
Example of usage in a view with authorization at this point:
1<html>
2<head>
3 <title>WS Client</title>
4 @vite(['resources/css/app.css', 'resources/js/app.js'])
5</head>
6<body>
7
8<textarea id="msg"></textarea>
9<button id="btn-base">Base</button>
10<button id="btn-broadcast">Broadcast</button>
11<ul id="output"></ul>
12
13<script type="text/javascript">
14 // page elements
15 const msg = document.getElementById('msg')
16 const btnBase = document.getElementById('btn-base')
17 const btnBroadcast = document.getElementById('btn-broadcast')
18 const output = document.getElementById('output')
19
20 const connect = (token) => {
21 let conveyor = new window.Conveyor({
22 protocol: '{{ $protocol }}',
23 uri: '{{ $uri }}',
24 port: {{ $wsPort }},
25 channel: '{{ $channel }}',
26 query: '?token=' + token,
27 onMessage: (e) => output.innerHTML = e,
28 onReady: () => {
29 btnBase.addEventListener('click', () => conveyor.send(msg.value))
30 btnBroadcast.addEventListener('click', () => conveyor.send(msg.value, 'broadcast-action'))
31 },
32 });
33 };
34
35 const getAuth = (callback) => {
36 fetch('/broadcasting/auth?channel_name={{ $channel }}', {
37 headers: {
38 'Accept': 'application/json',
39 },
40 })
41 .then(response => response.json())
42 .then(data => callback(data.auth))
43 .catch(error => console.error(error));
44 }
45
46 // for authorization:
47 document.addEventListener("DOMContentLoaded", () => getAuth(connect));
48 // for simple public connection:
49 // document.addEventListener("DOMContentLoaded", () => connect(''));
50</script>
51</body>
52</html>
Then, add the route for this view at your routes/web.php
file:
1use Illuminate\Support\Facades\Route;
2use Illuminate\Support\Facades\Auth;
3
4Route::get('/ws-client', function () {
5 Auth::loginUsingId(1); // here we authorize for the sake of the example.
6
7 return view('ws-client', [
8 'protocol' => config('broadcasting.connections.conveyor.protocol'),
9 'uri' => config('broadcasting.connections.conveyor.host'),
10 'wsPort' => config('broadcasting.connections.conveyor.port'),
11 'channel' => 'private-my-channel',
12 ]);
13});
Extra: Simple Conveyor Server for this example
You can use this simple server to test your broadcasting (and in production...):
1<?php
2// file: server.php
3
4include __DIR__ . '/vendor/autoload.php';
5
6use Conveyor\ConveyorServer;
7use Conveyor\Events\MessageReceivedEvent;
8use Conveyor\Events\PreServerStartEvent;
9
10(new ConveyorServer())
11 // if you want to see messages in the console
12 ->eventListeners([
13 Conveyor\Constants::EVENT_MESSAGE_RECEIVED => function (MessageReceivedEvent $event) {
14 var_dump($event->data);
15 },
16 ])
17 ->port(8181)
18 ->start();
Remember to install conveyor with composer require kanata-php/conveyor
and run the server with php server.php
.