Back to Blog
Lesson 32 of the Intermediate Laravel: Real-World Application Patterns course
LaravelJune 26, 20263 min read

Command Line Tools with Artisan: Automating Laravel Workflows

Learn how to build custom Artisan commands to automate development tasks. Master CLI arguments, options, and console interaction to streamline your Laravel app.

LaravelArtisanCLIAutomationConsolephpbackend

Previously in this course, we explored Advanced Dependency Injection with Service Providers to manage complex object lifecycles. In this lesson, we shift our focus from the web request lifecycle to the CLI. By building custom commands, you'll turn the terminal into a powerful dashboard for managing your application's state.

Why Custom Artisan Commands?

As your application grows, you'll inevitably face repetitive tasks: clearing cache, generating dummy data for specific states, or triggering cleanup scripts. While you could write these in controllers, putting them in the CLI makes them accessible to CI/CD pipelines and local development workflows.

Artisan is built on the Symfony Console component. It provides a standardized way to define inputs (arguments and options) and output formatting, ensuring your custom tools feel like first-class citizens alongside core Laravel commands.

Defining Your First Command

To create a new command, use the make:command Artisan generator. Let's build a tool for our project board that resets a specific project's task status to "pending" for debugging purposes.

Bash
php artisan make:command ResetProjectTasks

This creates a file in app/Console/Commands. Open it, and you'll see a $signature property. This string defines how the command is invoked and what inputs it accepts.

PHP
protected $signature = 'project:reset {projectId : The ID of the project} {--force : Force the reset even if project is locked}';

In the $signature above:

  • project:reset is the command name.
  • {projectId} is a required argument.
  • {--force} is an optional flag (boolean).

Implementing Logic and Console Interaction

Now, let's implement the handle() method. This is where your business logic lives. We'll inject our TaskService (which we built in our earlier lessons on Service-Oriented Task Management) to handle the actual data mutation.

PHP
public function handle(TaskService $taskService): void
{
    $projectId = $this->argument('projectId');
    $force = $this->option('force');

    if (!$force && $this->confirm("Are you sure you want to reset tasks for project {$projectId}?")) {
        return;
    }

    $taskService->resetTasksForProject($projectId);

    $this->info("Tasks for project {$projectId} have been reset successfully.");
}

Key interaction methods:

  • $this->argument('name') / $this->option('name'): Retrieve input.
  • $this->info('message'): Prints green text.
  • $this->error('message'): Prints red text.
  • $this->confirm('question'): Prompts the user for a yes/no response.
  • $this->table(['Header'], $data): Renders a clean ASCII table.

Hands-on Exercise

To advance our project board, your task is to create a command named project:stats {projectId}.

  1. Generate the command.
  2. In the handle() method, fetch the project using your repository layer.
  3. Use $this->table() to display the count of "Open", "In Progress", and "Completed" tasks for that project.
  4. If the project doesn't exist, use $this->error() to notify the user and exit.

Common Pitfalls

  • Over-Logic in Commands: Never put complex business logic inside the handle() method. Treat the command as a controller: it should only validate input, call a service or job, and format the output.
  • Ignoring Dependencies: Since Artisan commands are resolved via the service container, you can type-hint dependencies in the handle() method just like you do in controllers. Don't resolve them manually via app() inside the method.
  • Silent Failures: Always wrap your logic in try-catch blocks if the command interacts with external APIs or fragile data, and output the error using $this->error() so the user knows why the process stopped.

Recap

Custom Artisan commands are the backbone of developer productivity in Laravel. By leveraging the $signature property, you can create expressive interfaces for your background tasks. Always keep your command logic thin by delegating to services, and use the built-in console helpers (info, error, table) to provide clear feedback to the user.

Up next: Scheduled Tasks and Cron Jobs. We'll look at how to automate these commands so they run without manual intervention.

Similar Posts