Sooner or later, every codebase has a command whose name you can't remember. Say you have reports:generate-monthly. Half the team types reports:monthly from muscle memory and gets "Command not defined". You don't want to rename the command because runbooks, scripts, and Slack history all reference the old name. So you give it a second name.
The short version
Aliases are a Symfony Console feature, and Artisan is built on Symfony Console. Laravel supports them in three ways.
1. The $aliases property
class GenerateMonthlyReportCommand extends Command
{
protected $signature = 'reports:generate-monthly {reportId}';
protected $description = 'Generates the monthly report for the given id';
protected $aliases = ['reports:monthly'];
}
Laravel's Command constructor reads this property and calls Symfony's setAliases() for you. This is the approach we use.
2. The #[Aliases] attribute
Laravel 13 also has class attributes for command metadata:
use Illuminate\Console\Attributes\Aliases;
#[Aliases(['reports:monthly'])]
class GenerateMonthlyReportCommand extends Command
{
// ...
}
The #[Signature] attribute also accepts an aliases argument, so the signature and its aliases can sit together. Use whichever style your commands already use.
3. Overriding configure()
protected function configure(): void
{
parent::configure();
$this->setAliases(['reports:monthly']);
}
This works on any Laravel version because it uses plain Symfony. On recent versions, you rarely need it.
What you get
Both names run the same command with the same arguments and options:
php artisan reports:generate-monthly 123
php artisan reports:monthly 123
php artisan list shows the alias as its own entry and marks the canonical command with the alias in brackets, so people can see that the two names belong together:
reports:monthly Generates the monthly report for the given id
reports:generate-monthly [reports:monthly] Generates the monthly report for the given id
Gotchas
- An alias is only a name. Don't put arguments or options in it. The signature (
{reportId}) belongs to the command and is shared by every name. If you write'reports:monthly {reportId}'as an alias, Symfony takes the whole string as the name, including the placeholder. - Aliases must be unique. Run
php artisan listafter adding one to check that it doesn't collide with another command. - Scheduling and queues.
Schedule::command('reports:monthly'),$this->call(), andArtisan::call()all resolve aliases. Still, use the canonical name in code so a grep for the command finds every use. - Decide which name is canonical. The alias is a convenience. If you want people to move to the new name, make it the
$signaturename and keep the old one as the alias. That gives you a painless rename. - Test it. Run the command through its alias once in a test so a typo in the alias doesn't go unnoticed.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.