DEV Community

Kingsconsult
Kingsconsult

Posted on

Schedule a task to run at a specific time in laravel (CronJob)

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 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
2. Change into the directory

cd laraveljobscheduler/

change to the directory

Step 2: Setup Mail

For more explanation of this step, visit my previous article How to send email in Laravel 8 downwards using Gmail
.env file

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
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');
    }
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
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));
    }
}
Enter fullscreen mode Exit fullscreen mode

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');
    }
Enter fullscreen mode Exit fullscreen mode

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
This is the mail I got in my box
inbox

The complete code can be found in this github repo 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

Thank you for your time

Latest comments (2)

Collapse
 
kimdaiphong profile image
kimdaiphong

Are you sure this works?
As far as I know, Kernel.exe will be run only once. And at the time it is executed, fourthFridayMonthly is always a day of this month, for example $fourthFridayMonthly->format('d') is 29, but are you sure that 29th day of next month is its fourth Friday?

Collapse
 
ekosetiyo13 profile image
EkoSetiyo13

I think its work if add job in server. server can cronjob run command line every day, every week.