How to Use Arguments and Options in Laravel Commands (Creating Artisan Commands)
Table Of Contents
How to add arguments ({text}, {text?}, {text=default}, {text*}) and options (--force, --day=, -D, --tag=*) to your own Laravel artisan commands, with output checked on Laravel 13.
The original article was written with Laravel 8.
In November 2026, the same steps were checked again on Docker's php:8.4-cli (PHP 8.4.27) with Laravel 13.40.0, and a section on options was added.
Environment (original article)
Laravel Framework 8.60.0What will it look like in the end?
By adding arguments to a command, you can use that argument within the function of the command.
php artisan asitakara-ganbaru 明後日は休む
"明後日は休む"Creating a Command (steps used with Laravel 8)
Firstly, by "Creating a command",
php artisan your-choice-of-nameyou will be able to run the command.
It may seem intimidating at first, but it is remarkably easy to create.
Creating a file with a command
php artisan make:command TestCommandWe have created a file named TestCommand.
Check if the file is created in App\Console\Commands\TestCommand.php.
Deciding on the command name (decide on the ?? in php artisan ??)
Open TestCommand.php and look for the following line:
protected $signature = 'command:name';You can change this line. You can write any string of your choice, so give it a clear and understandable name.
protected $signature = 'asitakara-ganbaru';On Laravel 13.40.0, make:command no longer generates this $signature line; the name is written in a #[Signature('app:test-command')] attribute above the class instead (see "Laravel 13's #[Signature] attribute" below).
Replacing the attribute with protected $signature as above still worked on Laravel 13.40.0.
Next, write the function to be executed by this command
Look for the following line in the file:
public function handle()
{
return 0;
}Replace this code with the following:
public function handle()
{
dd('明日からがんばる');
}Trying out the command
Let's run the command.
php artisan asitakara-ganbaru
"明日からがんばる"If you see this output, it means the command was successful.
The command has been executed.
On Laravel 13.40.0, dd() also prints where it was called (// app/Console/Commands/TestCommand.php:13), and the command exits with code 1 because dd() stops the process.
For real commands, printing with $this->info() is easier to work with.
Setting Arguments
Next, let's try setting up the arguments.
protected $signature = 'asitakara-ganbaru {text}';public function handle()
{
$text = $this->argument('text');
dd($text);
}Try changing the code like this.
Set the name you want to use as an argument in the signature and call it with $this->argument.
Now, let's run the command with an argument.
php artisan asitakara-ganbaru 明後日は休む
"明後日は休む"It worked!
Setting up as optional
With the current setup, if you don't provide an argument, the command will throw an error like this:
Not enough arguments (missing: "text").The message was the same on Laravel 13.40.0.
Passing too many arguments gave Too many arguments to "asitakara-ganbaru" command, expected arguments "text".
To allow the command to run even without an argument, add the optional parameter.
protected $signature = 'asitakara-ganbaru {text?}';Simply add a "?" at the end.
Now, when you execute it without an argument:
php artisan asitakara-ganbaru
nullYou have successfully set it as optional.
Setting a default value
You can also set a default value when no argument is provided.
protected $signature = 'asitakara-ganbaru {text=明日から頑張る}';Let's run it.
php artisan asitakara-ganbaru
"明日から頑張る"Using an array as an argument
protected $signature = 'asitakara-ganbaru {text*}';php artisan asitakara-ganbaru 明日から頑張る 明後日も頑張る
array:2 [
0 => "明日から頑張る"
1 => "明後日も頑張る"
]Optional array
protected $signature = 'asitakara-ganbaru {text?*}';On Laravel 13.40.0, running it with no arguments returned an empty array [].
| signature | With no arguments (Laravel 13.40.0) | Value type |
|---|---|---|
{text} | Error (Not enough arguments) | string |
{text?} | null | string |
{text=明日から頑張る} | "明日から頑張る" | string |
{text*} | Error (Not enough arguments) | array |
{text?*} | [] | array |
Using options (checked on Laravel 13.40.0)
Options are passed as --name, so their order doesn't matter.
'app:ganbaru {text=明日から頑張る : What to do} {--force : Run without confirmation} {--D|day=明日 : When to start} {--tag=* : Tags (repeatable)}'{--force}takes no value:truewhen given,falseotherwise.{--D|day=明日}takes a value with the default明日;-Dis its shortcut.--day=来週,--day 来週and-D 来週all gave the same result.{--tag=*}can be repeated and is received as an array:--tag=運動 --tag=健康gave["運動","健康"].- Text after
:is shown inphp artisan help app:ganbaru.
Read them with $this->option('day').
Returning self::FAILURE from handle() made the exit code 1.
Passing a value to --force stopped with The "--force" option does not accept a value., and an undefined option stopped with The "--unknown" option does not exist.
Laravel 13's #[Signature] attribute
On Laravel 13.40.0, php artisan make:command TestCommand generated this file:
#[Signature('app:test-command')]
#[Description('Command description')]
class TestCommand extends Command
{
public function handle()
{
//
}
}Arguments and options are written inside the attribute in the same way as $signature, and classes in app/Console/Commands appeared in php artisan list without registering them anywhere.
Short commands can also be written in routes/console.php, where arguments are received as closure parameters:
Artisan::command('hello {name} {--yell}', function (string $name) {
$msg = "こんにちは、{$name}さん";
$this->info($this->option('yell') ? $msg.'!!' : $msg);
})->purpose('あいさつする');To call a command from code, pass arguments and options as an array: Artisan::call('app:ganbaru', ['text' => '早起き', '--force' => true, '--tag' => ['朝', '習慣']]) returned 0, and Artisan::output() returned the printed text.
Related Articles
How to Set Up Periodic Execution (Scheduler) in Laravel
Summary
That's all for now.
This article is based on the content written in the Laravel documentation with practical examples.
The Laravel 13 documentation is here.
It may be confusing at first to understand where everything is written, but let's gradually get used to it.
That's all for now!




