Schedule a task to run at a specific time in laravel (CronJob)
Tags: php, laravel, webdev, aws
Published: 2020-12-25 14:23:32

Good day and Merry Xmas,
Today, I am going to teach you how to schedule a task that can run at a specific time, when building an app, sometimes we might want to automate a task like sending out a newsletter daily/weekly/monthly, sending a report to the admin through email at the end of the day etc. All these task cannot be done manually, so we need a way to schedule it to run at a specific time of the day, week, month, or even every minute, so just relax and let's dive into it

Click on my [profile](https://dev.to/kingsconsult) to follow me to get more updates.

### **Step 1: Setup a new Laravel App**
**1. Install laravel**

> composer create-project laravel/laravel laraveljobscheduler 

![installing laravel 8](https://res.cloudinary.com/kingsconsult/image/upload/v1608900621/Schedule%20Job/1_xnv91p.png)
**2. Change into the directory**
>  cd laraveljobscheduler/

![change to the directory](https://res.cloudinary.com/kingsconsult/image/upload/v1608900624/Schedule%20Job/2_swcc1a.png)

### **Step 2: Setup Mail**
For more explanation of this step, visit my previous article [How to send email in Laravel 8 downwards using Gmail](https://dev.to/kingsconsult/how-to-send-email-in-laravel-8-downwards-using-gmail-3hid)
![.env file](https://res.cloudinary.com/kingsconsult/image/upload/v1608900624/Schedule%20Job/3_xjtiyx.png)

### **Step 3: Setup our Gmail Mailable**
For more explanation of this step, visit my previous article [How to send email in Laravel 8 downwards using Gmail](https://dev.to/kingsconsult/how-to-send-email-in-laravel-8-downwards-using-gmail-3hid)
**1. Make the mail**
> php artisan make:mail Gmail


```
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class Gmail extends Mailable
{
    use Queueable, SerializesModels;

    public $details;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($details)
    {
        $this->details = $details;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->subject('Mail from Laravel Job Scheduler')
            ->view('emails.gmail')
            ->from('Kingsconsult001@gmail.com');
    }
}
```
**2. Create the view**

```
<!DOCTYPE html>
<html>
<head>
    <title>kings</title>
</head>
<body>
    <h1>{{ $details['title'] }}</h1>
    <p>{{ $details['body'] }}</p>

    <p>Thank you for subscribing</p>
</body>
</html>
```

### **Step 4: Create a Job to send the mail**
We are going to use a Job to send the mail, so we are going to create a job

> php artisan make:job SendEmailJob

A new folder called **Jobs** will be created at **app/**, so subsequently new jobs will be stored in this folder, 
![new job](https://res.cloudinary.com/kingsconsult/image/upload/v1608900618/Schedule%20Job/5_uy1tbp.png)
Let's modify it to send out our mail 

```
<?php

namespace App\Jobs;

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

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

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {

        $details = [
            'title' => 'Thank you for subscribing to my newsletter',
            'body' => 'You will receive a newsletter every Fourth Friday of the month'

        ];
        Mail::to('kingsconsult001@gmail.com')->send(new Gmail($details));
    }
}
```
When calling a Job, the code inside the **handle()** method will be the one to run, so that is why we write our code in the handle() method.
From the code above, we import our Mail and Gmail class, we then pass the details of our mail to the Gmail class, my article on Sending mail explains this.

### **Step 5: Schedule the job to run at the specific time**
Lastly, We need to schedule when the job will be run, in order to do this, we are going to add the code in **app/Console/Kernel.php**, so let's modify the **schedule()** method
import these classes before the Kernel class
> use App\Jobs\SendEmailJob;
> use Carbon\Carbon;
```
   protected function schedule(Schedule $schedule)
    {
        // $schedule->command('inspire')->hourly();
            $now = Carbon::now();
        $month = $now->format('F');
        $year = $now->format('yy');

        $fourthFridayMonthly = new Carbon('fourth friday of ' . $month . ' ' . $year);

        $schedule->job(new SendEmailJob)->monthlyOn($fourthFridayMonthly->format('d'), '13:46');
    }
```
From the code above, We want to send out the newsletter every fourth Fridays of the month at 13:46 GMT, I used that day and time so that I will be able to test if my code works, 
First, I initialize the present time and extract the month and year, then I assign it to a variable, from the variable I created a time that will run every fourth Friday of the present month and year. 
Finally, schedule the job which runs monthly at the day and time that we specified.
**Testing**
Run the scheduler on the terminal
> php artisan schedule:work

![php artisan schedule:work](https://res.cloudinary.com/kingsconsult/image/upload/v1608900618/Schedule%20Job/7_eggcgk.png)
This is the mail I got in my box
![inbox](https://res.cloudinary.com/kingsconsult/image/upload/v1608900625/Schedule%20Job/6_folv46.png)

The complete code can be found in this github repo [Kingsconsult/laravel-schedule-job](https://github.com/Kingsconsult/laravel-schedule-job)

Follow me for more of my articles, you can leave comments, suggestions, and reactions.
I am open to any vacancy as a PHP (Laravel) backend engineer, I am also available for any job. 

[click the link to view my profile and follow me] (https://dev.to/kingsconsult)

Thank you for your time