Laravel Cron: The Definitive Guide

Solomon Eseme
Dec 28, 2020 · 10 min read

So you wish to automate some tasks in your newly created application with Laravel, say you want to send out birthday messages, promotional emails or you simply want to optimize and back up your database with Laravel Cron periodically.

Image for post
Image for post
laravel cron: the definitive guide

How do you achieve this in your Laravel project?

To automate this task, a task scheduling system is required and Cron Job seems like a perfect solution to your need, but Cron job itself is complicated and required strong domain knowledge to be able to set it up properly.

The solution is:

Laravel Cron Job offers a seemly, elegant, and easy to learn Task scheduling mechanism that suits exactly our problem.

So how do we get started?

In this article, we are going to explore everything you need to know about Cron Jobs, Laravel Cron Jobs, and the Task Scheduling System, we are going to build projects that leverage the Cron Job to demonstrate how it works and how easy it is to set it up in Laravel.

Before you dive in, if you’re a backend developer or looking at delving into this career path, join other developers to receive daily articles on backend development that will boost your productivity.

What is Cron?

If you’re a fan of Linux, you probably might have heard of Cron Job before, if not, well, now you know.

The Crontab contains all the specific Cron Jobs with their specific time and commands to execute.

So you can say that a CronJob is composed of two parts, The expression (Time) and the Command (Task).

Let’s see an example:

* * * * * * command/to/run

The expression part is the (* asterisk) part and the command part is the command/to/run which is the task to be executed at the specified time.

The 5 asterisks represent different times such as minute, hour, day of the month, month, and day of the week respectively.

To execute a particular task every five minutes, simply run:

5 * * * * command/to/run

Cron Job requires command line knowledge to master, Check Wikipedia for more information.

Also, you have to manage and update each Cron Job individually each time. That could easily become tedious because you have to SSH into your server each time you want to update or add a new Cron Job.

With Laravel, you don’t even need to master those commands or SSH into your server each time to add or modify existing Cron Job because Laravel Cron Job has simplified the process and provide you with methods to modify and add new Cron Job without SSHing into your server.

Let’s look at how?’

What is Laravel Cron?

Sounds good? Let’s understand how it works:

Inside app/Console/Kernel.php file, there is a method called schedule, this is where you may define all your Tasks to be executed periodically.

Defining Schedules/Jobs

Open the file at app/Console/Kernel.php and paste in the below code inside the schedule method.

/*** Define the application's command schedule.* @param  \Illuminate\Console\Scheduling\Schedule  $schedule* @return void*/protected function schedule(Schedule $schedule){ $schedule->call(function () {   $this->SendAdminEmail(); })->everyFiveMinutes();}

Using the call method, we can pass in Closure functions and the period we want our task to be executed, in our example above, we wanted our emails to be sent every five minutes hence everyFiveMinutes().

Laravel provides many other schedule frequency options like that, you can explore a list of them too. You can even schedule based on many parameters like Timezones, Truth Test Constraints (conditional), Environment Constraints, Day Constraints, and Between Time Constraints.

Scheduling an Artisan Command

Let’s see how?

My favorite command of all time in Laravel is php artisan optimize:clear to clear out all cached files.

Let’s see how we can ask Laravel Cron to run this command once a day:

To run artisan commands, use the command method of the app/Console/Kernel.php file like below.

/*** Define the application's command schedule.* @param  \Illuminate\Console\Scheduling\Schedule  $schedule* @return void*/protected function schedule(Schedule $schedule){  $schedule->command('php artisan optimize:clear')->daily();}

Scheduling a Queued Job

You can use the job method of the app/Console/Kernel.php to schedule such tasks like below.

/*** Define the application's command schedule.* @param  \Illuminate\Console\Scheduling\Schedule  $schedule* @return void*/protected function schedule(Schedule $schedule){   $schedule->job(new Birthday()->sendGift())->dailyAt('00:00');}

That will send birthday gifts to users daily at 00:00 hour.

Other Scheduling Methods

/*** Define the application's command schedule.* @param  \Illuminate\Console\Scheduling\Schedule  $schedule* @return void*/protected function schedule(Schedule $schedule){  $schedule->exec('node /home/public_html/scriptToBackUpDatabse.js')->weekly();}

The code above will execute a Node.js script to backup our database every week.

Executing one task at intervals

Like this:

$schedule->command('emails:send')->daily()->withoutOverlapping();// Or specifying time$schedule->command('emails:send')->daily()->withoutOverlapping(20); // wait for 20 minutes

Multiple Servers

You can append onOneServer() to the scheduler.

$schedule->command('generate:reports')->weekly()->onOneServer();

Background or Maintenance Mode

// Running in Background$schedule->command('emails:send')->weekly()->runInBackground();// In maintenance mode$schedule->command('emails:send')->evenInMaintenanceMode();

Scheduling Task Outputs

You can achieve this with the Laravel Cron task output methods:

// This sends output to the file path specified.$schedule->command('emails:send')
->daily()
->appendOutputTo($filePath);
// This sends output the a file and also sends out email to the address specified$schedule->command('report:generate')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('output@example.com');
// This sends failure output to the email address specified$schedule->command('report:generate')
->daily()
->emailOutputOnFailure('output@example.com');

Note that Task Outputs only work on command and exec methods only.

You might want to run some code before or after a task is executed, or even when a task is executed successfully or failed along the way.

Doing all these is really easy with Laravel Cron Job Task Hooks:

// Before and After hook$schedule->command('emails:send')
->daily()
->before(function () {
// The task is about to execute...
$this->updateStatusToSending();
})
->after(function () {
// The task has executed...
$this->updateStatusToSent();
});
// On success or failure hook$schedule->command('emails:send')
->daily()
->onSuccess(function () {
// The task succeeded...
$this->informAdmin('Email Sent successfully')
})
->onFailure(function () {
// The task failed...
$this->informAdmin('Email sending failed');
});

Take a break and subscribe to get access to our free Laravel tips that will improve your productivity.

Creating a new Project

Create a new Laravel scheduler

Let’s get started:

Run the following command to create a new Laravel project, or if you’re a complete beginner get started with Laravel Framework: The Ultimate guide.

composer create-project --prefer-dist laravel/laravel cron-demo

As mentioned above, there are different ways you can create Task Scheduling in Laravel:

By creating a new Artisan Command file or using the app/Console/Kernel.php file created already which we have demonstrated above.

Create a new Artisan Command

php artisan make:command myScheduler

After running the command, you will be presented with the following codes in app/Console/myScheduler.php.

<?phpnamespace App\Console\Commands;use Illuminate\Console\Command;class myScheduler extends Command{/*** The name and signature of the console command.* @var string*/protected $signature = 'command:name';/*** The console command description.* @var string*/protected $description = 'Command description';/*** Create a new command instance.* @return void*/public function __construct(){ parent::__construct();}/*** Execute the console command.* @return mixed*/public function handle() {  // }}

In our code below, the following line represents the signature of the command which we will be using to call the Laravel scheduler to perform the task.

protected $signature = 'command:name'; // Replace it with a good name protected $signature = 'birthday:send';

Next, we have the Description Property which is used to describe what the command is all about.

protected $description = 'Command description'; // Replace it with a Descriptive information protected $description = 'Send a happy birthday message to due users';

Lastly, we have the handle method which is where our task will be placed. Add the following code to the handle method to send birthday messages.

public function handle(){ $users = User::whereMonth('dob', '=', date('m'))->whereDay('dob', '=', date('d'))->get(); foreach ($users as $user) {  Mail::raw('Wishing you a Happy Birthday', function ($mail) use ($user) {  $email->to($user->email)  $email->from('no-reply@example.com')  $email->subject('Happy Birthday to you'); }); }}

The above code will just send out birthday messages to due users.

Note: Make sure to configure your mail and database parameters correctly.

Let’s move on to registering the Laravel Scheduler in the Kernel.php so Laravel can recognize and run our Task periodically.

Registering the scheduler

Go to app/Console/myScheduler.php and add the following codes.

<?phpnamespace App\Console;use Illuminate\Console\Scheduling\Schedule;use Illuminate\Foundation\Console\Kernel as ConsoleKernel;class Kernel extends ConsoleKernel{/*** The Artisan commands provided by your application.* @var array*/protected $commands = [ Commands\myScheduler::class,];/*** Define the application's command schedule.* @param  \Illuminate\Console\Scheduling\Schedule  $schedule* @return void*/protected function schedule(Schedule $schedule){ $schedule->command('birthday:send')->daily();}/*** Register the commands for the application.* @return void*/protected function commands() {  $this->load(__DIR__.'/Commands');  require base_path('routes/console.php'); }}

Great!

Now if you run php artisan list command, you should see it listed among the other available commands.

You can also send birthday messages by simply running an Artisan Command in your terminal.

php artisan birthday:send

Also, note that you can simply add everything inside the Kernel.php file instead of creating a new file and registering it. But this way is more elegant and organized than adding everything inside the Kernel.php file.

Running The Scheduler

Running the Scheduler locally

You can simply get your Laravel scheduler running by executing the following command in your project terminal.

php artisan schedule:work

Running in Shared Hosting

In CPanel, search for the Cron Job menu and click to open it. When on the page, choose your time and add your command to execute like below.

Image for post
Image for post

Make sure the to change the username appropriately.

Running with Terminal

Follow the steps below to run your scheduler in your terminal.
SSH into your production server.

Change directory to your Laravel project folder.

Run the following command with it or set up a process manager.

php artisan schedule:run

Running in Heroku

Running with a Cron Service

Let’s take a look at it:

Convert your Laravel Scheduler to a route and execute it using cURLs over https://cron-job.org/

Open your web.php file and add the following code.

Route::get('send', function(){ 
return Artisan::call('birthday:send');
});

The code above added a route to call the Birthday Scheduler we created earlier.

Now, to execute the command, go to https://cron-job.org and register, after that create a new Cron Job and reference the route in the URL input field.

Image for post
Image for post

If everything goes well, this will execute your route send every day at 00:00 hour which will, in turn, execute the Artisan command we specified earlier.

Conclusion

If you’re here, congratulations.

So far, we have discussed in detail Laravel Cron Jobs and we have listed the different ways we can use Laravel Cron Job or Schedulers, we have also discussed how to create a new Artisan Command file and demonstrated it with a project.

Lastly, we discussed how to run the scheduler where we discuss different ways you can possibly execute your scheduler.

If you have any questions or suggestions and observations as you read, please feel free to drop them at the comment section below, which will have to improve the article for others.

Originally published at https://masteringbackend.com on December 28, 2020.

Backend Developers

The ultimate publication for backend developers, DevOps engineers, and Software engineering.

Sign up for Backend Developers Newsletter

By Backend Developers

Chat and share with over a thousand backend engineers worldwide. We're building the biggest Backend Development virtual user group in the world. https://masteringbackend.com/slack Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Solomon Eseme

Written by

A Software Developer who’s geared towards building high performing and innovative products following best practices. Blog @ https://masteringbackend.com

Backend Developers

The ultimate publication for backend developers, DevOps engineers, and Software engineering. Blog @ https://masteringbackend.com

Solomon Eseme

Written by

A Software Developer who’s geared towards building high performing and innovative products following best practices. Blog @ https://masteringbackend.com

Backend Developers

The ultimate publication for backend developers, DevOps engineers, and Software engineering. Blog @ https://masteringbackend.com

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store