Scheduled tasks in Laravel are helpful when you need to run a task on a given schedule. You might need to export to an Excel file every night, or you might need to send a reminder to a user at a certain time. You could create a Cron job or scheduled task for each of these separately, but that could get hard to maintain, especially if you have a lot of scheduled tasks. Fortunately, Laravel has a built-in task scheduler that lets you define your schedules within your application, and execute them with a single Cron task.
Defining Schedules
Schedules are defined in the schedule
method of the App\Console\Kernal
class. For example, let’s assume we have a method to archive old orders that we want to run at the start of each month. We could define it like this:
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Models\Order;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
$schedule->call(function () {
Order::archive();
})->monthly();
}
}
There are a few different ways to define schedules:
- Closures: As seen in the example above, you can use the
call
method to run a closure that will run your scheduled code. - Invokable Objects: PHP classes that contain an
__invoke
method can also be run using thecall
method. For example, if you have an object calledOrderArchive
that handles the archiving logic, you could define the schedule using$schedule->call(new OrderArchive())->monthly()
. - Commands: Using the
command
method, you can schedule an Artisan command or system command. For example, if you have defined a command calledarchive:orders
to perform the archive, you could define the schedule using$schedule->command('archive:orders')->monthly()
. - Queued Jobs: Using the
job
method, you can schedule a queued job to run. For example, if you have a job defined calledArchiveOrders
to perform the archive, you could define the schedule using$schedule->job(new ArchiveOrders)->monthly()
.
Frequency
Laravel’s scheduler has over 30 methods to define how often your scheduled task will run. We won’t list all of them here, but here are a few examples:
- everyMinute();
- everyFiveMinutes();
- hourly();
- hourlyAt(20);
- daily();
- dailyAt(’13:00′);
- weekly();
- weeklyOn(1, ‘8:00’);
- monthly();
- twiceMonthly(1, 16, ’13:00′);
- yearly();
Constraints
You can further constrain your schedule. For example, if you want to schedule a notification that is only sent during working hours, you could do something like this:
$schedule->call(function () {
User::sendNotification();
})->hourly()
->weekdays()
->between("8:00", "18:00");
For a full list of frequencies and constraints you can go to this page in the Laravel documentation.
Custom Schedules
If none of the supplied frequencies or constraints allow you create the schedule you want, and you are familiar with writing Cron expressions, you can use the Cron method to create a custom schedule.
As an example, this schedule should run every five minutes starting at 1 p.m. and ending at 1:55 p.m., and then starting at 6 p.m. and ending at 6:55 p.m. every day:
$schedule->call(function() {
//Add schedule code here
})->cron('0/5 13,18 * * ?');
Running the Schedule
Laravel’s scheduler can be manually run by using the schedule:run
command. In a production environment, you would typically create a Cron task that runs artisan schedule:run
once per minute.
In a development environment, you typically wouldn’t run a Cron task. Instead, you could use the schedule:work
command, which would perform the schedule:run
command once per minute.
Further Scheduling Options
Laravel’s scheduler has a number of other options that are useful in certain circumstances. If you have a task that is run every few minutes, but could have a wildly varying execution time, you could use the withoutOverlapping()
method to prevent the task from running if the previous instance of the task is still running. Similarly, if you have a task that takes a long time to run, you can use the runInBackground()
method so that it doesn’t prevent other tasks from running before it is finished. If you have multiple servers running, you can use onOneServer()
to run the task on only one server.
For more details on the task scheduler, you can visit Laravel’s documentation.