January 30, 2019

Customizing your Laravel Broadcasting payloads

Customizing your Laravel Broadcasting payloads

One piece of the Laravel documentation that is somewhat glanced over in my opinion is the ability to customize the payload that is sent out to your Laravel Echo listeners upon new events or broadcast methods. This can be extremely important when results from the models passed to these events are large and/or bloated; for example: when you are storing chunks of HTML in your database.

By default, the Broadcasting functionality within Laravel serializes any and all classes/models that you pass to the events. What does this mean? Well lets say for example that you have a model that has 15 columns for each result, however during your select method you only query 3 columns; like so:

$user = \App\User::where('id', 6)
	->select(['id', 'name', 'email'])
	->first();

event(new \App\Events\UserLoggedOut($user));

If you pass this model to the event all 15 columns will be queried; regardless of what you select, or the number of unset methods you use. If you are using a service like that of Pusher, you could run into character limits that will ultimately lead to errors and failed messages.

Modifying your broadcasts

In order to prevent our broadcasts from erroring, we need to customize the payload that is sent to Pusher or any other platform. We can do that by playing a broadcastWith method within our event class. Let's to back to the example above, where we only want to broadcast the id, name, and email address. Our broadcastWith method would look like this:

/**
 * Specifically broadcasts the necessary array keys
 *
 * @return array
 */
public function broadcastWith()
{
    return [
        'user' => [
            'id' => $this->user->id,
            'name' => $this->user->name,
            'email' => $this->user->email,
        ]
    ];
}

By implementing this method, your broadcasts will be significantly simplified and thus carry a light payload. But that's not all! Because this is a method, and not a variable, you can perform additional logic within this method to conditionally add content to the payload. Refer to another example below:

/**
 * Specifically broadcasts the necessary array keys
 *
 * @return array
 */
public function broadcastWith()
{
    $payload = [
        'configuration' => [
            'id' => $this->configuration->id,
            'name' => $this->configuration->name,
            'user' => [
                'first_name' => $this->configuration->user->first_name,
                'last_name' => $this->configuration->user->last_name,
            ],
        ]
    ];

    if (!empty($this->configuration->jurisdictions)) {
        $jurisdiction = $this->configuration->jurisdictions->first();

        $payload['jurisdiction'] = [
            'id' => $jurisdiction->id
        ];
    }

    if (!empty($this->configuration->comments)) {
        $payload['comments'] = $this->configuration->comments;
    }

    return $payload;
}

What I have done is that I have assigned the initial associative array to a variable and performed some basic if-statements to conditionally add content to the payload.

While this isn't necessarily rocket science, using this method of customizing your broadcasts can simplify your application and save you a bunch of time wrestling with the Pusher/websockets APIs.