Last Updated on September 9, 2022
Most applications require some tasks to be run regularly and at a specific time. These tasks can be sending out promotional emails, creating weekly backups, or generating reports. To automate these tasks, Laravel Task Scheduler is an important utility. In this article, I am going to show you how to use Laravel Scheduler to automate tasks for your application. We are going to set a schedule for our tasks, activate the scheduler, and have the task run at a specific time every day.
Without further ado, let’s get started.
Laravel Cron Job Scheduling
Cron is a standard Unix utility that allows users to schedule tasks to run at certain intervals. Laravel offers a way of managing cron jobs on a server. The Scheduler allows us to define a command schedule within the application. While using the scheduler, only a single Cron entry is needed. All scheduled tasks are defined in the app/Console/Kernel.php file on the schedule method.
Let’s undertake the task scheduling using a simple example. I will create a custom artisan command that will send out monthly invoices to clients on a specific date every month.
Create New Artisan Command
For our case, we will assume we want to send out monthly invoices to clients on the 25th of every month. To do so, I will create a new artisan command that will carry out this task monthly. I will use Laravel Mail and Laravel PDF dependencies in this example.
To create a console command, use the following command:
php artisan make:command GenerateInvoiceCommand
This is going to create a class file in the app/Console/Commands folder in your Laravel application.
We need to add the command logic that will generate invoices. The logic is as shown:
The command above contains the $signature and the $description variables that define the terminal command and the description of the command respectively. Whenever you run the command php artisan generate:invoice, the handle() method is executed. As a result, I wrote the logic required to generate invoices in this method. I scheduled the generate invoice task to trigger an Invoice Job that generates the invoice. The Job is added to a Queue that runs every two seconds as shown on line 57. This means that the invoices will be generated and placed in a queue for seconds before being dispatched. Once the logic is done, we need to register the command in the Kernel class which is located in the app/Console folder.
You just need to update the $commands variable in the app/Console/Kernel.php file as shown.
If the variable is not present, you can add it and register your command.
protected $commands = [ 'App\Console\Commands\Your Command' ];
To verify the command has been registered and available in the artisan command list, the following command can be run on the terminal.
php artisan list
Scheduling Artisan Command
Laravel Scheduler provides a way of scheduling commands. All task schedules are defined in the app/Console/Kernel‘s schedule(Schedule $schedule) method. In our case, we are going to schedule this task (for generating monthly invoices) to run on the 25th of every month.
The schedule instructs the Laravel Scheduler to execute the command php artisan generate:invoice every month on the 25th at 9.00 a.m.
Scheduling Queued Jobs
The job method can be used to schedule a queued job. This method provides an efficient way of scheduling queued jobs. It allows us to schedule jobs that might take time to execute and we might want to run the task when the application is not being used as much. An example would be sending reminder emails to users. We can schedule the task to run at midnight when the application’s traffic is low.
Laravel Schedule Frequencies
Laravel provides more task schedule frequencies that can be assigned to a task. The frequencies are shown below:
|Run the task on a custom cron schedule|
|Run the task every minute|
|Run the task every two minutes|
|Run the task every three minutes|
|Run the task every four minutes|
|Run the task every five minutes|
|Run the task every ten minutes|
|Run the task every fifteen minutes|
|Run the task every thirty minutes|
|Run the task every hour|
|Run the task every hour at 17 minutes past the hour|
|Run the task every two hours|
|Run the task every three hours|
|Run the task every four hours|
|Run the task every six hours|
|Run the task every day at midnight|
|Run the task every day at 13:00|
|Run the task daily at 1:00 & 13:00|
|Run the task every Sunday at 00:00|
|Run the task every week on Monday at 8:00|
|Run the task on the first day of every month at 00:00|
|Run the task every month on the 4th at 15:00|
|Run the task monthly on the 1st and 16th at 13:00|
|Run the task on the last day of the month at 15:00|
|Run the task on the first day of every quarter at 00:00|
|Run the task on the first day of every year at 00:00|
|Run the task every year on June 1st at 17:00|
|Set the timezone for the task|
Additionally, Laravel provides additional schedule constraints to limit your tasks to run on a specific day of the week
|Limit the task to weekdays|
|Limit the task to weekends|
|Limit the task to Sunday|
|Limit the task to Monday|
|Limit the task to Tuesday|
|Limit the task to Wednesday|
|Limit the task to Thursday|
|Limit the task to Friday|
|Limit the task to Saturday|
|Limit the task to specific days|
|Limit the task to run between start and end times|
|Limit the task to not run between start and end times|
|Limit the task based on a truth test|
|Limit the task to specific environments|
These methods can be combined to create a more fine-tuned schedule for your task.
Preventing Task Overlaps
By default, scheduled tasks will run even if the previous instance of the task is still running. This can create memory leaks within your application and impact the performance of your application. To prevent this, withoutOverlapping method can be used.
In this example, the command is scheduled to send emails every minute when the task is not running.withoutOverlapping method prevents the Laravel Scheduler from creating a new instance of the command. This frees us from the headache of trying to anticipate the execution time of a task.
Activate the Laravel Scheduler
Now that we have learnt how to create and schedule tasks, we need to run them on a server for the tasks to be automated.
Running the Scheduler Locally
During development, we may need to test our scheduled tasks. Ideally, we would not want to add a scheduler cron entry because we have most of the control during development. To do so, we will use the schedule:work command. This command will run in the foreground and invoke the scheduler every minute until we terminate the command.
php artisan schedule:work
Running the Scheduler on a Server
Once we are done with development, we may need to run the scheduler on a live server. Since we have no control of the server, we need a command that will run in the background and execute scheduled tasks based on the server time. The schedule:run command makes this possible.
To configure the command, we need to add a cron entry to our server. All cron job entries are stored in a file called a crontab. To view all crons which are currently running on a server, we can run the command crontab –l. To access the crontab file we can use the crontab -e command. This opens the crontab file; where we can add the schedule:run command. The command to be added is shown below
* * * * * php /path-to-your-laravel-project/artisan schedule:run >> /dev/null 2>&1
Note: Please change path-to-your-laravel-project with your Laravel application path.
The last step is to restart cron for our changes to take effect
sudo service cron restart
After setting up the schedule, invoices will be generated every month on the 25th at 9.00 am.
Laravel Scheduler is a powerful utility that allows us to schedule tasks that run periodically. It provides us with the ability to focus on the logic and Laravel takes care of the rest. If you want to have even more control over your scheduled tasks by running them dynamically, you can check out this article.
I hope this article sheds some light on what Laravel Scheduler is and how to use it. Have questions? Let me know in the comments below. I’ll try my best to answer all of them.