Demystifying Laravel Queues
Tags: laravel, queue, jobs
Published: 2018-07-12 15:45:37

---
title: Demystifying Laravel Queues
published: true
description: 
tags: Laravel, Queue, Jobs
cover_image: https://thepracticaldev.s3.amazonaws.com/i/7p5cdwjpom4rdfylz9st.jpg
---


At some point, your application will need to listen for cues and emit an event for them. Those cues could be birthday or appointment reminders or expiry reminders for users of the trial version of your saas app. Unsurprisingly, Laravel has a built-in way to handle this graciously. Here, we would be sending out reminders to users of our amazing saas app who are on the trial version 15 days before their trial expires.
###First of All...Drivers
True to Laravel's reputation for including as many batteries as possible (which can definitely be good or bad), the framework comes with out-of-the-box support for different queue handlers including redis, beanstalk, amazon SQS and of course, relational databases, which we will be using here. There is also an amazing documentation on queue drivers [here](https://laravel.com/docs/5.6/queues#driver-prerequisites) so feel free to explore them.
    To use the database driver, we will need to create a table in our application database to hold the jobs and laravel provides a clean helper command for that. So we will create and run the necessary migrations like so:

```bash
php artisan queue:table
php artisan migrate
```
###Diving In
We want to equip our job with the ability of being continuously run in the background so we will create a new artisan command to trigger the task. Artisan commands are laravel's way of extending the already powerful command-line interface and there is an extensive documentation for it living [here](https://laravel.com/docs/5.6/artisan). Creating a new one is as simple as running:
```bash
php artisan make:command SendExpiryCommand
```
which generates a new class in `app/Console/Commands`. We will modify the `signature` and `description` attribute and the `handle()` method of this new class before using. 
   The `signature` is what we call from the CLI and has the format `command:name`, - think `db:seed`, `config:clear`, etc, as such, let's change our signature to `trial_expiry:notify` and the description to something actually more descriptive. Now the `handle()` method is what gets called when we run our shiny command and it is where our code (or most of it anyway) will live. Now, we are going to assume that our app has a `Trials` model with an `expires_in` field which holds the date the trial is supposed to expire as well as a `user_id` field which references our User model. So here is what our final handle() code looks like:

```php
/**
* Execute the console command.
*
* @return mixed
*/
public function handle(){
    //get the date of 15 days from now
    $actualDate = Carbon::now()->addDays(15);
    $actualDate = $actualDate->format('Y-m-d');
    $candidates = Trial::where('expires_in', '=', $actualDate)->get();      
    foreach ($candidates as $candidate) {
        SendExpiryNotification::dispatch($candidate);
    }
}
```
Our `SendExpiryNotification` is the actual queue-able job but it doesn't exist yet so let's create that:

```bash
php artisan make:job SendExpiryNotification
```

The above command will create a new class in `app/Jobs` which implements a `ShouldQueue` indicating that the job is to be run asynchronously. Don't worry if the Jobs folder doesn't exist yet, `artisan` will create it if it's not there. In the new class we meet another `handle()` method which like the command, is the sauce of our class which gets called when we run `dispatch` and it where our code will live. 
   Hey there! Now the some of the reasons we are passing a Trial instance instead of say, email, might be obvious but in addition to what is in your head, we want a fresh instance of our eloquent model just before running it from the queue which is exactly what this does. [Jacob Bennet](https://twitter.com/JacobBennett) has an amazing [blog post](https://gistlog.co/JacobBennett/e60d6a932db98985f160146b09455988) that details this. Also, our handle method won't take a trial instance as a parameter directly, instead, we feed the instance to the job constructor and call it from the handler.
Enough talk, show me the code! Alright, so here is what our `SendExpiryNotification` job looks like
```php
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Mail;

class SendExpiryNotification implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $trial;

    public function __construct($candidate) {
        $this->trial = $candidate;
    }

    public function handle()
    {
        $user = User::find($this->trial->user_id);
        Mail::raw('Hello, Your trial would be expiring soon and we wanted you to know!', function($message) {
            $message->to($user->email);
        });
    }
}
```
###...hang in there
Now that the big part is done, let's ~~see~~ make it work. We will start our queue listen with:
```bash
php artisan queue:listen
```

or:
```bash
php artisan queue:work --daemon
``` though general opinion is that the second works much better. So while our queue listeners are still running, we launch our command using the command signature which in this case would be
```bash 
php artisan trial_expiry:notify
```
Easy-peasy innit? Oh and by the way, [here](https://laravel.com/docs/5.6/queues) is laravel's queue documentation if you are that kind of person.