Laravel Task Scheduling

Introduction
In the past, you may have generated a Cron entry for each task you needed to schedule on your server. However, this can quickly become a pain, because your task schedule is no longer in source control and you must SSH into your server to add additional Cron entries.

Laravel’s command scheduler allows you to fluently and expressively define your command schedule within Laravel itself. When using the scheduler, only a single Cron entry is needed on your server. Your task schedule is defined in the app/Console/Kernel.php file’s schedule method. To help you get started, a simple example is defined within the method.

Starting The Scheduler
When using the scheduler, you only need to add the following Cron entry to your server. If you do not know how to add Cron entries to your server, consider using a service such as Laravel Forge which can manage the Cron entries for you:

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

This Cron will call the Laravel command scheduler every minute. When the schedule:run command is executed, Laravel will evaluate your scheduled tasks and runs the tasks that are due.

Defining Schedules
You may define all of your scheduled tasks in the schedule method of the App\Console\Kernel class. To get started, let’s look at an example of scheduling a task. In this example, we will schedule a Closure to be called every day at midnight. Within the Closure we will execute a database query to clear a table:

namespace App\Console;

use DB;
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 = [
        //
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            DB::table('recent_users')->delete();
        })->daily();
    }
}

In addition to scheduling using Closures, you may also use invokable objects. Invokable objects are simple PHP classes that contain an __invoke method:

$schedule->call(new DeleteRecentUsers)->daily();

Scheduling Artisan Commands
In addition to scheduling Closure calls, you may also schedule Artisan commands and operating system commands. For example, you may use the command method to schedule an Artisan command using either the command’s name or class:

$schedule->command(’emails:send –force’)->daily();
$schedule->command(EmailsCommand::class, [‘–force’])->daily();

Scheduling Queued Jobs
The job method may be used to schedule a queued job. This method provides a convenient way to schedule jobs without using the call method to manually create Closures to queue the job:

$schedule->job(new Heartbeat)->everyFiveMinutes();
// Dispatch the job to the “heartbeats” queue…
$schedule->job(new Heartbeat, ‘heartbeats’)->everyFiveMinutes();

Scheduling Shell Commands
The exec method may be used to issue a command to the operating system:
$schedule->exec(‘node /home/forge/script.js’)->daily();

Schedule Frequency Options
Of course, there are a variety of schedules you may assign to your task:

Method Description
->cron(‘* * * * *’); Run the task on a custom Cron schedule
->everyMinute(); Run the task every minute
->everyFiveMinutes(); Run the task every five minutes
->everyTenMinutes(); Run the task every ten minutes
->everyFifteenMinutes(); Run the task every fifteen minutes
->everyThirtyMinutes(); Run the task every thirty minutes
->hourly(); Run the task every hour
->hourlyAt(17); Run the task every hour at 17 mins past the hour
->daily(); Run the task every day at midnight
->dailyAt(’13:00′); Run the task every day at 13:00
->twiceDaily(1, 13); Run the task daily at 1:00 & 13:00
->weekly(); Run the task every week
->weeklyOn(1, ‘8:00′); Run the task every week on Monday at 8:00
->monthly(); Run the task every month
->monthlyOn(4, ’15:00’); Run the task every month on the 4th at 15:00
->quarterly(); Run the task every quarter
->yearly(); Run the task every year
->timezone(‘America/New_York’); Set the timezone
These methods may be combined with additional constraints to create even more finely tuned schedules that only run on certain days of the week. For example, to schedule a command to run weekly on Monday:

$schedule->call(function () {
    //
})->weekly()->mondays()->at('13:00');

// Run hourly from 8 AM to 5 PM on weekdays...
$schedule->command('foo')
          ->weekdays()
          ->hourly()
          ->timezone('America/Chicago')
          ->between('8:00', '17:00');

Below is a list of the additional schedule constraints:

Method Description
->weekdays(); Limit the task to weekdays
->sundays(); Limit the task to Sunday
->mondays(); Limit the task to Monday
->tuesdays(); Limit the task to Tuesday
->wednesdays(); Limit the task to Wednesday
->thursdays(); Limit the task to Thursday
->fridays(); Limit the task to Friday
->saturdays(); Limit the task to Saturday
->between($start, $end); Limit the task to run between start and end times
->when(Closure); Limit the task based on a truth test
->environments($env); Limit the task to specific environments

$schedule->command('reminders:send')
                    ->hourly()
                    ->between('7:00', '22:00');
$schedule->command('reminders:send')
                    ->hourly()
                    ->unlessBetween('23:00', '4:00');
$schedule->command('emails:send')->daily()->when(function () {
    return true;
});
$schedule->command('emails:send')->daily()->skip(function () {
    return true;
});
$schedule->command('report:generate')
         ->timezone('America/New_York')
         ->at('02:00')