php - Laravel WebSocket with Pusher Error when making POST Request

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 


I tested making a post to my /ws/log

{-code-2}

I kept getting

ErrorException: array_merge(): Expected parameter 2 to be an array, {-code-4} given in file /Users/alpha/Sites/jdoe/vendor/pusher/pusher-php-server/src/Pusher.php on line 518

I opened that file

{-code-3}

$params some how = {-code-4}

enter image description here

How do I continue to debug this further?


Edit

I removed my vendor/ and tried version 4.1 as suggested.

{-code-5}

I still face issue when making a POST to my route via POSTman.

enter image description here

Answer

Answer

Answer

Answer

Answer

- 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 ]; } }

Answer

Answer

Answer

Answer

Answer

- /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); });

Answer

Answer

Answer

Answer

Answer

- route Route::post('ws/log', 'BroadcastController@logEvent');

Answer

Answer

Answer

Answer

Answer

- 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); } }

Answer

Answer

Answer

Answer

Answer

- CSRF /Users/alpha/Sites/jdoe/app/Http/Middleware/VerifyCsrfToken.php protected $except = [ '/ws/log' ];

Answer

Answer

Answer

Answer

Answer

- 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

Answer

Answer

Answer

Answer

Answer

- 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|||{ "type": "poop" }|||$all_params = array_merge($post_params, $params);|||null|||"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" },

Answer

Solution:

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

Source