Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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

MethodWhen 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>&1

Checking

php artisan schedule:list
php artisan schedule:work

The 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.

Thanks for reading!

Donate to the site — we work hard for you.