Eventing in Laravel 5.1

Access all tutorials in sprocket icon.

September 30, 2015 from author Bill Keck.

Eventing in Laravel 5.1.

Background.

One of the things that can be intimidating when you are a beginner is the idea of eventing. What is it? When to use it?

Probably the easiest way to get it is through a simple example. Think of an email message that gets sent out upon registration of a new user. In the old procedural way of doing it, you would just hardcode some kind of send command directly in the controller.

That does work, however if your application grows, you might have all kinds of messages that need to go out to users, things like support request responses, upgrade messages, and of course the previously mentioned signup responder.

When you put it in that context, it makes a lot of sense to have a clean and extensible way to handle these situations. Events are perfect for this. Laravel events are not limited to email, but this is an excellent way to look at how they work.

Mailhelper.

In my project, I decided to do a fairly robust mail helper class that handles many types of email responses. I haven’t built the system response for registration, so I’m using a class I built to handle support messages. I think if I try to go through that whole process, it would make the tutorial too long, so I’m not going to go through that entire class. Instead, I’ll just show you how I’m calling it:



$contactMailhelper = new ContactMailHelper('supportMessage', $request);

So what that does is it hands in the type of message we want, a support message, and also an instance of the request, which tells it which pre-formatted response we want to send, based on form input. I also did a token replace for username. It’s a fairly involved class, so don’t worry if it doesn’t make sense in a glance. All you need to know is that when it returns, the $contactMailerhelper holds the sendto email address, the subject, the body, and view that’s needed for the message.

If you don’t know how to send email from Laravel, this tutorial will help you with that too. After getting our instance of $contactMailhelper, we are then going to fire our event:



$contactMailhelper = new ContactMailHelper('supportMessage', $request);

event(new RespondedToSupportRequest($contactMailhelper));

Bind the Event to a Listener.

Ok, I’m getting ahead here by showing how it’s called, I’m going to come back to this because we have not yet created our event to handle it. So how do we that? Fortunately, Laravel makes this incredibly easy.

In your Providers folder, you will see a file named EventServiceProvider.php. Inside of that, we will put the following in the $listen array:



protected $listen = [
        'App\Events\RespondedToSupportRequest' => [
            'App\Listeners\MailUserSupportResponse',
        ],
    ];

This binds the event RespondedToSupportRequest to the listener MailUserSupportResponse. Neither of those two classes exist yet either.

Generate the event classes.

We can quickly get both of those classes up and running by using the following artisan command on the command line:



php artisan event:generate

So that command looks for any bindings that don’t currently have classes and creates them for you. If you run that coommand, you now have RespondedToSupportRequest.php in the events folder. You will also have MailUserSupportResponse.php in your listeners folder. Both files are stubbed out and namespaced and in the correct folders. This is just awesome workflow.

We’re not really building a working example, but you should get enough out of this tutorial to be able to setup your own events. So don’t worry if you would rather have a UserSignedUp event with an EmailWelcomeNewUser, just make the changes to the EventServiceProvider $listen array and generate your own events.

I’m going to continue on, because there are few more things that you should know that are really helpful.

Let’s tackle the listener first. All we have to do is modify the handle method:



public function handle(RespondedToSupportRequest $event)
{
        $data = ['body'         => $event->contactMailHelper->emailBody,
                 'emailAddress' => $event->contactMailHelper->emailAddress,
                 'emailSubject' => $event->contactMailHelper->emailSubject,
                 'emailView'    => $event->contactMailHelper->emailView,
        ];

        Mail::queue($data['emailView'],$data , function($message) use($data)
        {
            $message->to($data['emailAddress'])->subject($data['emailSubject']);
        });
}

In the signature of the handle method, we hand in an instance of the event. Then I’ve set up an array for the $data that we need to send an email. In my case, I’m receiving the configuration through the contactMailHelper object that I’m handing in.

If you want to simplify and hardcode in values for a signup email, for example, just replace that code with your own values. You can see that $data is just an array and we are simply using the array keys to hand in the appropriate values at the right places.

I’m also going to show you how to pass along an object, so you will be able to hand in the user instance if you want and you can use something like $event->user->email if you wish. Hopefully that will be clear.

Sending the mail.

The part that actually sends the mail is the following:



Mail::queue($data['emailView'],$data , function($message) use($data)
        {
            $message->to($data['emailAddress'])->subject($data['emailSubject']);
        });

I should mention that Laravel is going to look for view in the emails folder that is in the view folder. The second parameter is $data, so we have So your $data[’emailView’] key should hold that value. Inside the view itself, the array key is a variable you can call:



{{ $body }}

That will display whatever is in the email if you have set that in your $data array. You can reference the Laravel Docs on this as well.

Also, if you want to use Mail, you need to include the use statement:



use Illuminate\Support\Facades\Mail;

Also notice, I’m using the queue method as opposed to the send method. What this does is allow you to push the message to the queue, so you don’t have to stop the user experience to wait for it to process. Instead it gets pushed onto the queue, where it goes out asynchronously from the browser.

The Event.

Let’s go to the RespondedToSupportRequest.php and modify the constructor:



public function __construct($contactMailhelper)
    {
        $this->contactMailHelper = $contactMailhelper;
    }

We also need to set a property:



public $contactMailHelper;

So in my implementation, I’m handing in my instance of $contactMailHelper, which sets all the email properties I’m going to need. If you are doing a simple autoresponder on registration, you might just want to pass along the user id, so you can get the rest of what you need in the handle method of the listener. Like I said, this is not a working example for you, just trying to help you understand how it works.

At any rate, the constructor sets the property, which will be passed along to the listener when the event fires.

So, putting it all together, we call the event in your controller like so:



event(new RespondedToSupportRequest($contactMailhelper));

Don’t forget the use statement:



use App\Events\RespondedToSupportRequest;

That’s just one line you can pop into your controller(don’t forget the use statement), so you don’t end up with mail code in your controller that doesn’t really belong there.

So the $contactMailerhelper object is passed into the event and we know that is set through the constructor of the event for us to use in the listener. The handle method of the listener does the bulk of the work:



public function handle(RespondedToSupportRequest $event)
{
        $data = ['body'         => $event->contactMailHelper->emailBody,
                 'emailAddress' => $event->contactMailHelper->emailAddress,
                 'emailSubject' => $event->contactMailHelper->emailSubject,
                 'emailView'    => $event->contactMailHelper->emailView,
        ];

        Mail::queue($data['emailView'],$data , function($message) use($data)
        {
            $message->to($data['emailAddress'])->subject($data['emailSubject']);
        });
}

This tutorial might seem complicated if you are reading along, but in reality this is very simple. Here are the 4 simple steps to implementation:

1. Bind your event to listener in the EventServiceProvider file.
2. Use the artisan command to generate the necessary classes, php artisan event:generate
3. Modify the constructor of your event class if you need to pass in an $id variable or other object and set the property.
4. Code your handler in your listener class to do act on the event, in our example, it’s sending an email.

Tip: Remember your use statements.

Once you get this, you can see how wonderful and easy Laravel eventing really is. It’s a beautiful part of the laravel architecture, with simple syntax and many advanced features that you can read up on in the docs.

I hope you have enjoyed this tutorial and found it useful. Click on the sprocket icon at the top of the page to see all tutorials. Please comment, share, and like if you can, thanks!

I don’t have a donate button, but If you would like to support my work and learn more about Laravel, you can do so by buying one of my books, Laraboot: laravel 5* For Beginners, I really appreciate it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s