控制台输出(参数和选项)

命令行最有趣的部分,就是你可以利用参数(arguments)和选项(options)。参数和选项,能够让你从终端(terminal)向命令(command)动态地传入信息。

使用控制台参数 

参数是字符串 - 由空格(space)分隔 - 跟在命令名称的后面。参数是有顺序的,而且可以是可选的或必须的。例如,添加一个可选的 last_name 参数到命令中,并且令 name 参数必填:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ...
use Symfony\Component\Console\Input\InputArgument;
 
class GreetCommand extends Command
{
    // ...
 
    protected function configure()
    {
        $this
            // ...
            ->addArgument('name', InputArgument::REQUIRED, 'Who do you want to greet?')
            ->addArgument('last_name', InputArgument::OPTIONAL, 'Your last name?')
        ;
    }
}

现在你可以在命令中访问 last_name 参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ...
class GreetCommand extends Command
{
    // ...
 
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $text = 'Hi '.$input->getArgument('name');
 
        $lastName = $input->getArgument('last_name');
        if ($lastName) {
            $text .= ' '.$lastName;
        }
 
        $output->writeln($text.'!');
    }
}

命令可以像下面列出的这样使用:

1
2
3
4
5
$  php bin/console app:greet Fabien
Hi Fabien!
 
$  php bin/console app:greet Fabien Potencier
Hi Fabien Potencier!

也可以让参数接收“值的列表”(假设你希望欢迎你的所有朋友)。但只有最后一个参数才能是列表:

1
2
3
4
5
6
7
$this
    // ...
    ->addArgument(
        'names',
        InputArgument::IS_ARRAY,
        'Who do you want to greet (separate multiple names with a space)?'
    );

要使用列表,指定任意多的名字即可:

1
$  php bin/console app:greet Fabien Ryan Bernhard

你可以访问到作为数组的 names 参数:

1
2
3
4
$names = $input->getArgument('names')
if (count($names) > 0) {
    $text .= ' '.implode(', ', $names);
}

有三种参数变体可用:

InputArgument::REQUIRED
参数必填。如果不提供,则命令不运行;
InputArgument::OPTIONAL
参数可选,因此可以忽略;
InputArgument::IS_ARRAY
参数可以包含任意多个值。因此,它必须使用在参数列表中的最后一个

你可以像下面这样同时使用 IS_ARRAYREQUIRED 以及 OPTIONAL :

1
2
3
4
5
6
7
$this
    // ...
    ->addArgument(
        'names',
        InputArgument::IS_ARRAY | InputArgument::REQUIRED,
        'Who do you want to greet (separate multiple names with a space)?'
    );

使用控制台选项 

和参数不同,选项是没有顺序之分的 (也就是你可以按任意顺序指定它们) ,指定选项是用两个中杠 (如 --yell)。选项 始终 是可选的,而且可以被设置为接收一个值 (如 --dir=src) ,或者是一个布尔值旗标而不需要值 (如 --yell)。

例如,向一个“信息在一行之内应该被输出指定的次数”的命令中添加一个新的选项:

1
2
3
4
5
6
7
8
9
$this
    // ...
    ->addOption(
        'iterations',
        null,
        InputOption::VALUE_REQUIRED,
        'How many times should the message be printed?',
        1
    );

接下来,使用这个命令来多次输出信息:

1
2
3
for ($i = 0; $i < $input->getOption('iterations'); $i++) {
    $output->writeln($text);
}

现在,运行命令时,你可以可选地指定一个 --iterations 旗标了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# no --iterations provided, the default (1) is used
# 不提供--iterations,使用的默认值是(1)
$  php bin/console app:greet Fabien
Hi Fabien!
 
$  php bin/console app:greet Fabien --iterations=5
Hi Fabien
Hi Fabien
Hi Fabien
Hi Fabien
Hi Fabien
 
# the order of options isn't important / 选项的顺序是无所谓的
$  php bin/console app:greet Fabien --iterations=5 --yell
$  php bin/console app:greet Fabien --yell --iterations=5
$  php bin/console app:greet --yell --iterations=5 Fabien

你还可以为选项声明一个“以单个中杠开头”的单字符的快捷方式,像是 -i:

1
2
3
4
5
6
7
8
9
$this
    // ...
    ->addOption(
        'iterations',
        'i',
        InputOption::VALUE_REQUIRED,
        'How many times should the message be printed?',
        1
    );

另有四种选项的变体可用:

InputOption::VALUE_IS_ARRAY
此选项可接收多个值 (如 --dir=/foo --dir=/bar);
InputOption::VALUE_NONE
此选项不接受输入的值 (如 --yell);
InputOption::VALUE_REQUIRED
此选项的值必填 (如 --iterations=5), 但选项本身仍然是可选的;
InputOption::VALUE_OPTIONAL
此选项的值可有可无 (e.g. --yell--yell=loud)。

你可以像下面这样同时使用 VALUE_IS_ARRAYVALUE_REQUIREDVALUE_OPTIONAL :

1
2
3
4
5
6
7
8
9
$this
    // ...
    ->addOption(
        'colors',
        null,
        InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
        'Which colors do you like?',
        array('blue', 'red')
    );

当你创建命令时,使用选项并令其可选地接受一个值,是不受约束的。但是,当这个选项并没有具体值 (command --language) ,或者它根本没被使用 (command) 的时候,你是没有办法区分这些情况的。两种情况下,此选项所收到的值都是 null

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)