0

Artisan — Laravel's CLI tool name and what 'artisan' refers to

Beginner5 min read·eng-14-014

Concept

Artisan — Laravel's command-line interface (CLI). The name "Artisan" comes from the concept of a skilled craftsperson — someone who creates things with care. Taylor Otwell chose it to reflect the craftsmanship philosophy of Laravel.

What Artisan is: A PHP script (artisan in the project root) that runs a Symfony Console application. Every Artisan command is a class extending Illuminate\Console\Command. The app is fully bootstrapped when Artisan runs.

Built-in commands (some important ones):

  • php artisan serve — local development server.
  • php artisan make:model, make:controller, make:migration, make:job, etc. — code generation.
  • php artisan migrate, migrate:rollback, migrate:fresh — database migrations.
  • php artisan route:list — list all registered routes.
  • php artisan cache:clear, config:cache, view:cache, optimize — cache management.
  • php artisan queue:work, queue:listen — process queued jobs.
  • php artisan schedule:run — run scheduled tasks (called from cron every minute).
  • php artisan tinker — interactive REPL.
  • php artisan test — run PHPUnit tests.

Custom Artisan commands: Create with php artisan make:command SendDailyReport. The command has a $signature (name + argument/option definitions) and a handle() method.

Calling Artisan programmatically: Artisan::call('cache:clear') — useful in tests and Tinker. Returns the exit code.

Scheduling: php artisan schedule:run is triggered every minute by a cron job. The scheduler (in routes/console.php) defines what runs and when.

Code Example

bash
# Making and running Artisan commands
php artisan make:command GenerateDailyReport
php artisan make:model Order -m              # model + migration
php artisan make:controller OrderController --api --model=Order
php artisan make:job ProcessPayment
php artisan make:middleware EnsureEmailIsVerified

php artisan route:list --path=api/v1         # filter routes
php artisan config:cache                     # merge all config into one file
php artisan optimize                         # config + route + view cache
php
<?php
// Custom Artisan command
namespace App\Console\Commands;

use Illuminate\Console\Command;

class GenerateDailyReport extends Command
{
    // Command signature: name + arguments + options
    protected $signature = 'reports:daily
                            {date? : The date (Y-m-d). Defaults to yesterday}
                            {--email= : Email to send the report to}
                            {--dry-run : Show what would be sent without sending}';

    protected $description = 'Generate and send the daily sales report';

    public function handle(): int
    {
        $date   = $this->argument('date') ?? now()->subDay()->toDateString();
        $email  = $this->option('email') ?? 'team@example.com';
        $dryRun = $this->option('dry-run');

        $this->info("Generating report for {$date}...");

        $stats = Order::whereDate('created_at', $date)
                      ->selectRaw('COUNT(*) as count, SUM(total) as revenue')
                      ->first();

        $this->table(
            ['Date', 'Orders', 'Revenue'],
            [[$date, $stats->count, '$' . number_format($stats->revenue, 2)]]
        );

        if ($dryRun) {
            $this->warn('Dry run — email not sent');
            return Command::SUCCESS;
        }

        \Mail::to($email)->send(new DailyReportMail($date, $stats));
        $this->info("Report sent to {$email}");

        return Command::SUCCESS; // 0 = success, 1 = failure
    }
}

// Scheduling in routes/console.php (Laravel 11+) or App\Console\Kernel (Laravel 10):
use Illuminate\Support\Facades\Schedule;
Schedule::command('reports:daily')->dailyAt('06:00')->emailOutputOnFailure('admin@example.com');
Schedule::command('queue:restart')->hourly();
Schedule::command('horizon:snapshot')->everyFiveMinutes();

// Calling from code
\Artisan::call('cache:clear');
\Artisan::call('reports:daily', ['date' => '2026-01-01', '--email' => 'ceo@example.com']);