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.

Create a free account to save this page, take notes and track your progress. Sign in

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.

A command with options, output and an exit code
<?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?

  1. A cron entry per task
  2. One cron entry runs php artisan schedule:run every minute
  3. It runs inside the web server
  4. Via a queue worker only
Show answer

Answer: One cron entry runs php artisan schedule:run every minute

Was this page helpful?