Laravel Tutorial · Beyond the Basics · Lesson 25 of 27
Artisan Commands and Scheduling
Write your own Artisan commands with arguments, options and output, and schedule tasks to run every minute, hour or day.
Custom commands
Generate a command with php artisan make:command PruneOldReports. A command has a signature (name, {arguments} and {--options}), a description, and a handle() method that can print output (info, line, error, table), ask questions, show progress bars, and return an exit code. Simple commands can be closures in routes/console.php.
Scheduling
Instead of one cron entry per task, add a single cron line that runs php artisan schedule:run every minute, and declare tasks in routes/console.php:
Schedule::command('reports:prune --days=30')->daily()->at('03:00');
Schedule::job(new SendDigest)->weeklyOn(1, '8:00')->withoutOverlapping();
Schedule::call(fn () => Cache::forget('stats'))->everyFifteenMinutes();
php artisan schedule:list shows what will run and when.
<?php
use Illuminate\Support\Facades\Artisan;
Artisan::command('reports:prune {--days=30 : Delete reports older than this} {--dry-run}', function () {
$days = (int) $this->option('days');
$reports = collect([['name' => 'q1.pdf', 'age' => 120], ['name' => 'q2.pdf', 'age' => 40], ['name' => 'oct.pdf', 'age' => 12]]);
$old = $reports->filter(fn ($r) => $r['age'] > $days);
foreach ($old as $report) {
$this->line("- {$report['name']} ({$report['age']} days old)");
}
if ($this->option('dry-run')) {
$this->info("Dry run: {$old->count()} report(s) would be deleted.");
return 0;
}
$this->info("Deleted {$old->count()} report(s) older than $days days.");
return 0;
})->purpose('Delete old reports');
Artisan::call('reports:prune', ['--days' => 30, '--dry-run' => true]);
echo Artisan::output();
$exitCode = Artisan::call('reports:prune', ['--days' => 100]);
echo Artisan::output(), "exit code: $exitCode\n";
Output
- q1.pdf (120 days old) - q2.pdf (40 days old) Dry run: 2 report(s) would be deleted. - q1.pdf (120 days old) Deleted 1 report(s) older than 100 days. exit code: 0
Run this on your computer — see “Get Started” for setup.
Test yourself
How does Laravel's scheduler run on a server?
A cron entry per taskOne cron entry runs php artisan schedule:run every minuteIt runs inside the web serverVia a queue worker only
Show answer
Answer: One cron entry runs php artisan schedule:run every minute