Task scheduling
Clean up old records at night, refresh exchange rates every hour, send a report on Mondays — such tasks run on a schedule. Normally each gets its own line in the server's cron. In Laravel the schedule is described in the project's code, and the server needs just one entry.
The schedule
Tasks are described in the routes/console.php file:
use Illuminate\Support\Facades\Schedule;
Schedule::command('reports:send')->weeklyOn(1, '9:00');
Schedule::command('model:prune')->daily();The first line runs an Artisan command on Mondays at nine in the morning, the second every day at midnight.
What can be scheduled
use App\Jobs\UpdateExchangeRates;
use Illuminate\Support\Facades\DB;
Schedule::job(new UpdateExchangeRates)->hourly();
Schedule::call(function () {
DB::table('sessions')->where('last_activity', '<', now()->subWeek()->timestamp)->delete();
})->daily();
Schedule::exec('node /var/www/scripts/report.js')->monthly();job() puts a job on the queue, call() runs a function, exec() runs an operating system command.
Frequency
| Method | When it runs |
|---|---|
everyMinute() | Every minute |
everyFiveMinutes() | Every five minutes |
hourly() | At the start of every hour |
daily() | Every day at midnight |
dailyAt('13:00') | Every day at the given time |
weekly() | Once a week |
monthly() | On the first day of every month |
cron('0 */6 * * *') | By a cron expression |
Constraints
Schedule::command('emails:send')
->weekdays()
->between('8:00', '18:00')
->timezone('Europe/London');
Schedule::command('backup:run')
->daily()
->environments(['production']);Preventing overlaps
If a task takes longer than the interval between runs, the next run starts on top of the previous one. withoutOverlapping() prevents that:
Schedule::command('import:products')
->everyFiveMinutes()
->withoutOverlapping();On a site with several servers add onOneServer() so that the task runs on only one of them.
Running on the server
A single line goes into the server's cron. It calls the scheduler every minute, and the scheduler decides what is due:
* * * * * cd /var/www/blog && php artisan schedule:run >> /dev/null 2>&1Checking
php artisan schedule:list
php artisan schedule:workThe first command shows every task and its next run time. The second runs the scheduler in the terminal — this is how a schedule is checked during development, without setting up cron.
Common mistake
Times in the schedule are in the application's time zone — UTC by default. A dailyAt('9:00') task runs at nine in the morning Greenwich time, which may be a different hour where you are. Set the zone in the timezone setting of config/app.php or with the timezone() method on the task itself.