I'm trying to integrate web socket into my laravel project. I did all steps from here
composer require pusher/pusher-php-server
/Users/alpha/Sites/jdoe/config/broadcasting.php
https://dashboard.pusher.com/apps/888
app_id = "888"
key = "***"
secret = "333"
cluster = "us2"
|
V
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=888
PUSHER_APP_KEY=***
PUSHER_APP_SECRET=333
PUSHER_APP_CLUSTER=us2
.env.example + .env
npm install --save laravel-echo pusher-js
npm run watch
---------------------------------------------------
php artisan make:event logEvent
<?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 logEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
private $data;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('logEventChannel');
}
public function broadcastWith()
{
return [
'data' => $this->data
];
}
}
---------------------------------------------------
/Users/alpha/Sites/jdoe/resources/js/app.js
require('./bootstrap');
Echo.channel('logEventChannel').listen('logEvent', (e) => {
// console.log(typeof JSON.parse(JSON.stringify(e))) //object
// console.log(typeof JSON.parse(JSON.stringify(e.data))) //string
// console.log(JSON.parse(e.data)); //decode or parse it
let data = JSON.parse(e.data);
/*=============================
= Debug =
=============================*/
console.log('data ===== ',data);
});
---------------------------------------------------
route
Route::post('ws/log', 'BroadcastController@logEvent');
---------------------------------------------------
Controller
<?php
namespace App\Http\Controllers;
use App\Events\LogEvent;
use Illuminate\Http\Request;
class BroadcastController extends Controller
{
public function vnfevent(Request $request)
{
$body = json_decode($request->getContent(),true);
dd($body); 💥
$json = json_encode($body);
broadcast(new LogEvent($json));
return response()->json($body,200);
}
}
---------------------------------------------------
CSRF
/Users/alpha/Sites/jdoe/app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
'/ws/log'
];
---------------------------------------------------
TEST
POSTman
ws/log
{
"type": "poop"
}
place a dd in broadbast
arrived !!
array:1 [
"type" => "poop"
]
ErrorException: array_merge(): Expected parameter 2 to be an array, null given in file
---------------------------------------------------
Debug the crashing line
/Users/alpha/Sites/jdoe/vendor/pusher/pusher-php-server/src/Pusher.php
dd($post_params, $params);
$all_params = array_merge($post_params, $params);
array:3 [â–¼
"name" => "App\Events\logEvent"
"data" => array:1 [â–¼
"data" => "{"type":"poop"}"
]
"channels" => array:1 [â–¼
0 => "logEventChannel"
]
]
Look correct
I tested making a post to my /ws/log
{
"type": "poop"
}
I kept getting
ErrorException: array_merge(): Expected parameter 2 to be an array, null given in file /Users/alpha/Sites/jdoe/vendor/pusher/pusher-php-server/src/Pusher.php on line 518
I opened that file
$all_params = array_merge($post_params, $params);
$params some how = null
How do I continue to debug this further?
I removed my vendor/ and tried version 4.1 as suggested.
"require": {
"php": "^7.2.5",
"doctrine/dbal": "^2.10",
"fideloper/proxy": "^4.2",
"fruitcake/laravel-cors": "^1.0",
"guzzlehttp/guzzle": "^6.3",
"intervention/image": "^2.3",
"laravel/framework": "^7.0",
"laravel/tinker": "^2.0",
"laravelcollective/html": "~6.0",
"pusher/pusher-php-server":"^4.1"
},
I still face issue when making a POST to my route via POSTman.
So for this problem, in fact that was an issue in Laravel and it is solved now
using (laravel 8.29.0) or higher versions.
So pusher-http-php library v5.0.1 and Laravel v8.29.0 will work fine for you.
Another Solution: is to downgrade pusher to version 4.1 on composer.json and this version seems to work fine with older laravel versions (older than 8.29.0).
If you want to solve the problem with your current installation:
The problem is that the calls for trigger function, at least on laravel 8 is not sending the right parameters, so in PusherBroadcaster.php
and pusher-php-server/Pusher.php
there are 2 calls for trigger function which are:
$this->pusher->trigger(
$this->formatChannels($channels), $event, $payload, $socket, true
);
and
public function trigger($channels, $event, $data, $params = array(), $already_encoded = false)
You will need to change the Pusher
only.
1- Change (Line 496).
$data_encoded = $this->crypto->encrypt_payload($channels[0], $already_encoded ? $data : json_encode($data));
To:
$data_encoded = $this->crypto->encrypt_payload($channels[0], $already_encoded && !is_array( $data) ? $data : json_encode($data));
2- Change (Line 499).
$data_encoded = $already_encoded ? $data : json_encode($data);
To:
$data_encoded = $already_encoded && !is_array( $data) ? $data : json_encode($data);
3- Change (Line 518)
$all_params = array_merge($post_params, $params);
To:
$all_params = array_merge($post_params, is_array($params) ? $params:[]);
4- Change (Line 542)
return $result;
To:
return $response;
and this will make it works for you fine.
Note: As I said it is resolved in v8.29.0 of Laravel. Link
Note: Or you can use composer require pusher/pusher-php-server ^4.1
Note that:
The main problem is that $param
is null
in this case and it didn't check if this value is array()
so when the code tries to merge array()
with null
.
Resources:
Link_1 Link_2 Link_3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With