Understanding how Console Arguments and Options Are Handled

Symfony Console applications follow the same docopt standard used in most CLI utility tools. This article explains how to handle edge-cases when the commands define options with required values, without values, etc. Read this other article to learn about using arguments and options inside Symfony Console commands.

Symfony コンソール アプリケーションは、ほとんどの CLI ユーティリティ ツールで使用されているのと同じ docopt 標準に従っています。この記事では、コマンドが必要な値を持つオプション、値のないオプションなどを定義する場合のエッジケースの処理方法について説明します。Symfony コンソール コマンド内で引数とオプションを使用する方法については、この他の記事をお読みください。

Have a look at the following command that has three options:

3 つのオプションがある次のコマンドを見てください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
namespace Acme\Console\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'demo:args', description: 'Describe args behaviors')]
class DemoArgsCommand extends Command
{
    protected function configure()
    {
        $this
            ->setDefinition(
                new InputDefinition([
                    new InputOption('foo', 'f'),
                    new InputOption('bar', 'b', InputOption::VALUE_REQUIRED),
                    new InputOption('cat', 'c', InputOption::VALUE_OPTIONAL),
                ])
            );
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // ...
    }
}

Since the foo option doesn't accept a value, it will be either false (when it is not passed to the command) or true (when --foo was passed by the user). The value of the bar option (and its b shortcut respectively) is required. It can be separated from the option name either by spaces or = characters. The cat option (and its c shortcut) behaves similar except that it doesn't require a value. Have a look at the following table to get an overview of the possible ways to pass options:

foo オプションは値を受け入れないため、false (コマンドに渡されない場合) または true (ユーザーが --foo を渡した場合) のいずれかになります。 bar オプション (およびそれぞれの b ショートカット) の値は必須です。オプション名とは、スペースまたは = 文字で区切ることができます。 cat オプション (およびその c ショートカット) は、値を必要としないことを除いて、同様に動作します。オプションを渡す方法の概要については、次の表を参照してください。
Input foo bar cat
--bar=Hello false "Hello" null
--bar Hello false "Hello" null
-b=Hello false "=Hello" null
-b Hello false "Hello" null
-bHello false "Hello" null
-fcWorld -b Hello true "Hello" "World"
-cfWorld -b Hello false "Hello" "fWorld"
-cbWorld false null "bWorld"

Things get a little bit more tricky when the command also accepts an optional argument:

コマンドがオプションの引数も受け入れる場合、事態は少し複雑になります。
1
2
3
4
5
6
// ...

new InputDefinition([
    // ...
    new InputArgument('arg', InputArgument::OPTIONAL),
]);

You might have to use the special -- separator to separate options from arguments. Have a look at the fifth example in the following table where it is used to tell the command that World is the value for arg and not the value of the optional cat option:

オプションと引数を区切るには、特殊な -- セパレータを使用する必要がある場合があります。次の表の 5 番目の例を見てください。ここでは、World が arg の値であり、オプションの cat オプションの値ではないことをコマンドに伝えるために使用されています。
Input bar cat arg
--bar Hello "Hello" null null
--bar Hello World "Hello" null "World"
--bar "Hello World" "Hello World" null null
--bar Hello --cat World "Hello" "World" null
--bar Hello --cat -- World "Hello" null "World"
-b Hello -c World "Hello" "World" null