Command base class — $signature, handle(), output helpers
Concept
Command base class provides the structure all framework commands inherit from. It defines $signature, handle(), and output helpers. The base class parses the signature, integrates with input/output objects, and provides the developer-facing API.
$signature parsing: The signature string defines the command name, arguments, and options in one concise string: 'make:model {name} {--migration}'. The base class parses this to register the command with the CLI framework and to provide $this->argument() and $this->option().
handle(): int: The main method. Returns an exit code: 0 = success (use self::SUCCESS), 1 = failure (self::FAILURE), 2 = invalid input (self::INVALID).
Output helpers (wrapping an Output object):
$this->info(string $message): Green text.$this->error(string $message): Red text to stderr.$this->line(string $message): Default color.$this->warn(string $message): Yellow text.$this->table(array $headers, array $rows).
Input helpers:
$this->argument(string $name): Get an argument value.$this->option(string $name): Get an option value.$this->ask(string $question): Prompt user for input.$this->confirm(string $question): Yes/No prompt.$this->choice(string $question, array $choices): Selection.
Dependency injection via constructor: Commands resolved from the container can declare constructor dependencies.
Code Example
<?php
namespace Framework\Console;
abstract class Command
{
public const SUCCESS = 0;
public const FAILURE = 1;
public const INVALID = 2;
protected string $signature = '';
protected string $description = '';
protected string $name = '';
protected InputInterface $input;
protected OutputInterface $output;
abstract public function handle(): int;
// Called by Application when running the command
public function run(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
return $this->handle();
}
// --- Input helpers ---
protected function argument(string $name): mixed
{
return $this->input->getArgument($name);
}
protected function option(string $name): mixed
{
return $this->input->getOption($name);
}
protected function ask(string $question, ?string $default = null): string
{
return $this->output->ask($question, $default) ?? $default ?? '';
}
protected function confirm(string $question, bool $default = false): bool
{
return $this->output->confirm($question, $default);
}
protected function choice(string $question, array $choices, mixed $default = null): string
{
return $this->output->choice($question, $choices, $default);
}
// --- Output helpers ---
protected function info(string $message): void { $this->output->info($message); }
protected function error(string $message): void { $this->output->error($message); }
protected function warn(string $message): void { $this->output->warning($message); }
protected function line(string $message): void { $this->output->writeln($message); }
protected function newLine(int $count = 1): void { $this->output->newLine($count); }
protected function table(array $headers, array $rows): void
{
$this->output->table($headers, $rows);
}
public function getName(): string { return $this->name ?: $this->parseNameFromSignature(); }
public function getDescription(): string { return $this->description; }
public function getSignature(): string { return $this->signature; }
private function parseNameFromSignature(): string
{
// Extract 'make:model' from 'make:model {name} {--migration}'
return trim(explode('{', $this->signature)[0]);
}
}
// Example command using the base class
class ListUsersCommand extends Command
{
protected string $signature = 'users:list {--role= : Filter by role} {--limit=20 : Max results}';
protected string $description = 'List all users';
public function handle(): int
{
$role = $this->option('role');
$limit = (int) $this->option('limit');
$query = User::query()->limit($limit);
if ($role) $query->where('role', '=', $role);
$users = $query->get();
$this->table(
['ID', 'Name', 'Email', 'Role'],
array_map(fn($u) => [$u->id, $u->name, $u->email, $u->role], $users)
);
$this->info("Total: {$users->count()} users");
return self::SUCCESS;
}
}