Real-time Apps with Laravel 5.1 and Event Broadcasting

Christopher Thomas
Christopher Thomas
Share

In Laravel 5.1, the framework includes functionality called broadcasting events that makes it easy to create real-time apps in PHP. With this new functionality, an app can publish events to various cloud-based real-time PubSub solutions, like Pusher, or to Redis.

Laravel 5.1

In this article, we examine a simple todo app and turn it into a real-time app using Laravel’s broadcasting events.

Download and Install App

The easiest way to get started is to spin up an instance of Homestead Improved. If you don’t want to use Homestead Improved, you must have git and composer installed on your system.

We will put the starter code in a directory called todo-app by cloning a git repo.

git clone https://github.com/cwt137/l51-todo-app todo-app

After the cloning is finished, go into the todo-app directory. We need to install all the app dependencies by running the following command (depending on how your composer is set up, the command might be slightly different):

composer install

After all the dependencies are installed, we must set up our database.

php artisan migrate

Testing the Non Real-time App

This app is now functional, but without the real-time functionality provided by Laravel’s broadcasting events. Open up the homepage in two browsers and put them side by side so you can do a comparison. If you do not have two different browsers, you can use two browser windows.

Manipulate the todo list in the first browser window. Then do something in the second browser window. You will notice that the other browser window that you were not in does not update without hitting the refresh button. This is because there is no real-time functionality. Let’s add some.

Adding Real-time Capabilities to the App

Adding real-time capabilities will allow both browser windows to update their content without waiting for a hit of the refresh button.

In this example, we will define three Laravel event classes that get triggered at various times in our app. One event is the ItemCreated event that is triggered when a new item is created. The second event is the ItemUpdated event that is triggered when an item is updated (is marked completed or uncompleted). The last is the ItemDeleted event that is triggered when an item is removed from the todo list.

Broadcasting Events

To do broadcasting events, we will create a regular Laravel event, but we will implement an interface called ShouldBroadcast. If Laravel sees that an event class implements ShouldBroadcast it knows that it is a broadcasting event. This interface requires us to define a method inside our event class called broadcastOn. It should return an array of strings which are the channels that this event should be broadcasted on.

To create the event classes we need, run some artisan commands

php artisan make:event ItemCreated
php artisan make:event ItemUpdated
php artisan make:event ItemDeleted

Open up app/Events/ItemCreated.php and replace the contents with the code below:

<?php

namespace App\Events;

use App\Item;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class ItemCreated extends Event implements ShouldBroadcast
{
    use SerializesModels;

    public $id;

    /**
     * Create a new event instance.
     *
     * @param Item $item
     * @return void
     */
    public function __construct(Item $item)
    {
        $this->id = $item->id;
    }

    /**
     * Get the channels the event should be broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return ['itemAction'];
    }
}

Laravel’s event system will serialize this object and broadcast it out on the real-time cloud system using the itemAction channel. The next couple of events are similar to the first.

Open up app/Events/ItemUpdated.php and replace the contents with the code below:

<?php

namespace App\Events;

use App\Item;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class ItemUpdated extends Event implements ShouldBroadcast
{
    use SerializesModels;

    public $id;
    public $isCompleted;

    /**
     * Create a new event instance.
     *
     * @param Item $item
     * @return void
     */
    public function __construct(Item $item)
    {
        $this->id = $item->id; 
        $this->isCompleted = (bool) $item->isCompleted;
    }

    /**
     * Get the channels the event should be broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return ['itemAction'];
    }
}

Open up app/Events/ItemDeleted.php and replace the contents with the code below:

<?php

namespace App\Events;

use App\Item;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class ItemDeleted extends Event implements ShouldBroadcast
{
    use SerializesModels;

    public $id;

    /**
     * Create a new event instance.
     *
     * @param Item $item
     * @return void
     */
    public function __construct(Item $item)
    {
        $this->id = $item->id;
    }

    /**
     * Get the channels the event should be broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return ['itemAction'];
    }
}

Database Events

There are a few places in which we could fire events for our project. We could do it inside the controller, or inside the database event triggers. In this example we will use the database triggers because it feels more natural to me and doesn’t fill up the controller with extra stuff. Also, by putting the event firing logic inside the database layer, it makes it possible to fire events when a command-line program is built or when an app is built as a cron job.

Eloquent, the database library, fires events every time a model is created, saved after an update, or deleted. We will listen to those events so we can fire our own broadcasting events. This will be done through a service provider.

Open the file at app/Providers/AppServiceProvider.php and replace the contents with the following code:

<?php

namespace App\Providers;

use Event;
use App\Item;
use App\Events\ItemCreated;
use App\Events\ItemUpdated;
use App\Events\ItemDeleted;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Item::created(function ($item) {
            Event::fire(new ItemCreated($item));
        });

        Item::updated(function ($item) {
            Event::fire(new ItemUpdated($item));
        });

        Item::deleted(function ($item) {
            Event::fire(new ItemDeleted($item));
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

Pusher

The real-time cloud service we will use for this example is Pusher. Support for this service is built into Laravel and is the easiest to set up.

Registration

We must register for an account to get a set of credentials. After registering on the Pusher website, go to the admin screen and create a new app called todo-app. Take note of the app_id, key and secret. We will need those later.

Pusher PHP Server Library

For our app to use Pusher, we must add the server library to our project. This is done via composer.

composer require 'pusher/pusher-php-server:2.2.1'

JavaScript

We will add some JavaScript to the bottom of our homepage. Open up resources/views/index.blade.php, the blade template for the homepage, and put the following code just before the closing body tag

<script src="//js.pusher.com/2.2/pusher.min.js"></script>
<script>
    var pusher = new Pusher("{{ env(PUSHER_KEY) }}");
</script>
<script src="js/pusher.js"></script>

The code above loads the Pusher Javascript client library, instantiates the Pusher object by passing our key into the constructor, and loads our Pusher specific app logic.

In the starter app, items were deleted and added based on events happening on the page (form submit, delete icon clicked, etc). This is why when we opened two browser windows, both did not get updated. One browser window can’t see what is going on in the other browser window. To make the app real-time, we will add and delete items based upon the events coming from Pusher. But first, open up public/js/app.js and comment out all the calls to the addItem() and removeItem() functions. Be sure not to delete the two function declarations at the top of the file.

Create the file public/js/pusher.js and put the following code into it.

( function( $, pusher, addItem, removeItem ) {

var itemActionChannel = pusher.subscribe( 'itemAction' );

itemActionChannel.bind( "App\\Events\\ItemCreated", function( data ) {

    addItem( data.id, false );
} );

itemActionChannel.bind( "App\\Events\\ItemUpdated", function( data ) {

    removeItem( data.id );
    addItem( data.id, data.isCompleted );
} );

itemActionChannel.bind( "App\\Events\\ItemDeleted", function( data ) {

    removeItem( data.id );
} );

} )( jQuery, pusher, addItem, removeItem);

The app subscribes to the itemAction channel. By default, Lavavel uses the qualified class name of the event object as the Pusher event name. The Javascript code above sets up listeners for the three events App\Events\ItemCreated, App\Events\ItemUpdated, and App\Events\ItemDeleted. There are callbacks that handle what happens when these events are triggered. As you can see the calls to getItem and removeItem were moved into the callbacks for the various events. So now, items are added or removed based on a Pusher event instead of a user event.

Testing the Realtime App

To test out this app, you need to set the keys for Pusher. By default, Laravel looks at environment variables for the Pusher information. Open up the .env file and put the following lines at the bottom.

PUSHER_KEY=YOUR_PUSHER_KEY
PUSHER_SECRET=YOUR_PUSHER_SECRET
PUSHER_APP_ID=YOUR_PUSHER_APP_ID

This will set up the variables. Where YOUR_PUSHER_KEY, YOUR_PUSHER_SECRET, YOUR_PUSHER_APP_ID are your Pusher assigned key, secret and app_id, respectively.

Open up two browser windows again and manipulate the todo list in one of them. You will see the list automatically update in the other browser window without having to hit the refresh button.

Final Thoughts

Although not covered in this article, the framework used is extensible and if Laravel does not support your real-time solution, there might be a composer package with the appropriate broadcast driver for it already. Or you can create your own broadcast driver along with a service provider to load it.

With the new broadcasting events functionality built into Laravel 5.1, it is now easier for PHP developers to create real-time apps. This new real-time capability unlocks many possibilities that were only available to apps written for other platforms like Node.js.

Frequently Asked Questions (FAQs) about Real-Time Apps with Laravel 5.1 and Event Broadcasting

What is event broadcasting in Laravel 5.1?

Event broadcasting in Laravel 5.1 is a feature that allows the application to broadcast events to the client-side of a web application, so updates can be shown to the user in real-time. This is particularly useful in applications where immediate updates are crucial, such as in chat applications, live feeds, or real-time analytics. Laravel’s event broadcasting allows you to use either Pusher or Redis to broadcast events, but you can also write your own broadcaster.

How does Laravel’s event broadcasting work?

Laravel’s event broadcasting works by allowing you to broadcast your server-side Laravel events to your client-side JavaScript application. When an event is fired on the server-side, it’s broadcasted to the client-side. The client-side JavaScript application listens for these events and reacts accordingly, such as by updating the user interface.

How can I set up event broadcasting in Laravel 5.1?

Setting up event broadcasting in Laravel 5.1 involves a few steps. First, you need to configure your broadcasting settings in your .env file. You can choose to use either Pusher or Redis for broadcasting. Then, you need to register the event and the listener in the EventServiceProvider. After that, you can fire the event using the event function. On the client-side, you need to listen for the event using Laravel Echo or a similar library.

What is Laravel Echo and how does it relate to event broadcasting?

Laravel Echo is a JavaScript library that makes it easy to handle event broadcasting in Laravel applications. It provides a clean, fluent API for subscribing to channels and listening for events broadcast by Laravel. With Laravel Echo, you can easily listen for events on the client-side and update your user interface in real-time.

Can I use event broadcasting with Laravel 5.1 for real-time updates in my application?

Yes, you can use event broadcasting with Laravel 5.1 for real-time updates in your application. This is one of the main use cases for event broadcasting. By broadcasting events from the server-side to the client-side, you can update the user interface in real-time without requiring the user to refresh the page.

How can I secure my event broadcasting in Laravel 5.1?

You can secure your event broadcasting in Laravel 5.1 by using Laravel’s built-in authentication and authorization features. You can specify that certain events should only be broadcast to authenticated users, or you can specify that certain events should only be broadcast to users who have a specific authorization level.

Can I broadcast events to specific users with Laravel 5.1?

Yes, you can broadcast events to specific users with Laravel 5.1. This is done by using private channels. When you broadcast an event on a private channel, only the users who are authorized to listen to that channel will receive the event.

What are the benefits of using event broadcasting in Laravel 5.1?

Using event broadcasting in Laravel 5.1 has several benefits. It allows you to update the user interface in real-time, which can greatly improve the user experience. It also allows you to decouple your server-side and client-side code, which can make your application easier to maintain and scale.

Can I use event broadcasting with Laravel 5.1 for real-time analytics?

Yes, you can use event broadcasting with Laravel 5.1 for real-time analytics. By broadcasting events whenever a user performs an action, you can track these actions in real-time and update your analytics dashboard without requiring a page refresh.

What are the alternatives to Laravel’s event broadcasting for real-time updates?

There are several alternatives to Laravel’s event broadcasting for real-time updates. These include using WebSockets directly, using a service like Firebase, or using a library like Socket.IO. However, Laravel’s event broadcasting provides a clean, easy-to-use API for real-time updates, and it integrates well with the rest of the Laravel framework.