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.
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
)