Scheduled Tasks in Laravel

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.

scheduled tasks in laravel

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 the call method. For example, if you have an object called OrderArchive 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 called archive: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 called ArchiveOrders 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.

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 * * ?');

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.