phpvue.jslaravel-8pusherpusher-js

Implementing Laravel 8 broadcasting with Pusher and Laravel Echo in a Vue frontend


I am trying to implement event broadcasting and notification with laravel. The goal is to broadcast a private message to a logged in users via notifications.

I created this event, see code below:

<?php

namespace App\Events;

use App\Models\User;
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 TradingAccountActivation implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

     /**
     * The authenticated user.
     *
     * @var \Illuminate\Contracts\Auth\Authenticatable
     */
    public $user;
    public $message;

    /**
     * Create a new event instance.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
        $this->message = "{$user->first_name} is ready to trade";
    }

   
    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('user.'.$this->user->id);
    }

}

The event is to be fired for every newly verified user, so I put the event in the project's email verification controller, see code below:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Verified;
use App\Events\TradingAccountActivation;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
class VerifyEmailController extends Controller
{
    /**
     * Mark the authenticated user's email address as verified.
     *
     * @param  \Illuminate\Foundation\Auth\EmailVerificationRequest  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function __invoke(EmailVerificationRequest $request)
    {
        if ($request->user()->hasVerifiedEmail()) {
            return redirect()->intended(RouteServiceProvider::HOME.'?verified=1');
        }

        if ($request->user()->markEmailAsVerified()) {
            event(new Verified($request->user()));
        } 

        event(new TradingAccountActivation($request->user()));
        return redirect()->intended(RouteServiceProvider::HOME.'?verified=1');
           
    }
}

At this point the event fails with this error message:

ErrorException
array_merge(): Expected parameter 2 to be an array, null given

The stack trace points to pusher on the line with an asterisk:

Illuminate\Foundation\Bootstrap\HandleExceptions::handleError
C:\xampp\htdocs\spa\vendor\pusher\pusher-php-server\src\Pusher.php:391

        $path = $this->settings['base_path'].'/events';

         // json_encode might return false on failure

        if (!$data_encoded) {

            $this->log('Failed to perform json_encode on the the provided data: {error}', array(

                'error' => print_r($data, true),

            ), LogLevel::ERROR);

        }

         $post_params = array();

        $post_params['name'] = $event;

        $post_params['data'] = $data_encoded;

        $post_params['channels'] = array_values($channels);

    *    $all_params = array_merge($post_params, $params);

         $post_value = json_encode($all_params);

         $query_params['body_md5'] = md5($post_value);

Laravel Telescope confirms that the event failed with these details:

Job Details Time April 6th 2021, 9:05:01 AM (1:56m ago) Hostname Adefowowe-PC Status failed Job App\Events\TradingAccountActivation Connection sync Queue
Tries - Timeout - Tags App\Models\User:75Auth:75failed Authenticated User ID 75 Email Address j@doe.com

along with the data the event was meant to emit:

{
"event": {
"class": "App\Events\TradingAccountActivation",
"properties": {
"user": {
"id": 75,
"uuid": "75da67ef-d6f8-4cd0-9d57-e1dcf66c1f5e",
"first_name": "John",
"last_name": "Doe",
"mobile_phone_number": "08033581133",
"verification_code": null,
"phone_number_isVerified": 0,
"phone_number_verified_at": null,
"email": "j@doe.com",
"email_verified_at": "2021-04-06T08:04:49.000000Z",
"created_at": "2021-04-06T08:03:56.000000Z",
"updated_at": "2021-04-06T08:04:49.000000Z"
},
"message": "John is ready to trade",
"socket": null
}
},
"tries": null,
"timeout": null,
"connection": null,
"queue": null,
"chainConnection": null,
"chainQueue": null,
"chainCatchCallbacks": null,
"delay": null,
"afterCommit": null,
"middleware": [
],
"chained": [
]
}

Curiously, it appears the broadcast channel was created and a connection established despite the event failing. Refreshing the error page appears to proceed with the next action of the controller which is to redirect to the dashboard of the authenticated user. At this point a broadcast connection is established. See Laravel Telescope details below with the payload:

Request Details
Time    April 6th 2021, 10:02:38 AM (10s ago)
Hostname    Adefowowe-PC
Method  POST
Controller Action   \Illuminate\Broadcasting\BroadcastController@authenticate
Middleware  auth:web
Path    /broadcasting/auth
Status  302
Duration    1043 ms
IP Address  127.0.0.1
Memory usage    12 MB
Payload
Headers
Session
Response
{
"socket_id": "131623.12865758",
"channel_name": "private-user.${this.user.id}"
}

Since the event failed, I didn't expect expect a broadcast channel to be established or for the subsequent listeners and notifications broadcast message to fire.

I can't figure out why the event failed, i.e. how to deal with the exception "array_merge(): Expected parameter 2 to be an array, null given", or how to fix it.

Or if it has anything to do with subsequent codes for receiving/logging/displaying the broadcast message.

Thanks.


Solution

  • This issue is resolved in the version 8.29.0. You will either need to upgrade to the version specified, or downgrade the version of pusher-http-php (composer require pusher/pusher-php-server ^4.1)