Console Component命令行组件在Symfony 3.2中获得了极大提升,多数都是关乎DX开发体验改进的(developer experience)。本文是console系列第一篇,将讨论这些新功能中的四个。

命令假名将不再作为独立命令显示 

在最佳实践中,我们推荐把命令“命名空间化”,以避免冲突,同时改进程序的组织性。但是,对于频繁使用的命令,还是定义快捷方式更方便:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class VeryLongNameCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            ->setName('app:very:long:name')
            ->setDescription('Lorem Ipsum...')
            // ...
            ->setAliases(['foo'])
        ;
    }
 
    // ...
}

上例中,命令既能以./bin/console app:very:long:name来执行,也能以./bin/console foo执行。虽然只是一条命令,但Symfony将以两个单独的命令来呈现。

1
2
3
4
5
6
$  ./bin/console
 
Available commands:
  foo                      Lorem Ipsum...
 app:
  app:very:long:name       Lorem Ipsum...

在Symfony 3.2中,假名被包含在原始命令的“行内”,减轻了命令行输出的卡顿:

1
2
3
4
5
$  ./bin/console
 
Available commands:
 app:
  app:very:long:name       [foo] Lorem Ipsum...

静默模式中仍然显示错误 

当运行一个Symfony命令时,如果你添加了-q--quiet选项,那么输出(output)将被配置为OutputInterface::VERBOSITY_QUIET级别。此举会令命令行不输出任何信息,包括报错信息。

在Symfony 3.2中我们改进了-q--quiet选项,抑制了Logger::ERROR级别日志信息之外的全部信息。这样你就不会再遗失任何错误信息了。

对单一命令程序提供更好的支持 

用Symfony构建单一命令程序(single command application)是可能的,但是需要你做出一些改变,以避免持续传入命令的名字。在Symfony 3.2中,我们改进了Application基类,以更好地支持单一命令程序。

首先,像以前一样定义一个命令,而创建console程序。然后,设置一个唯一的命令作为默认命令,并传递true作为setDefaultCommand()的第二个参数。它能把程序转换成一个“单一命令程序”。

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Console\Application;
 
$command = new \FooCommand();
 
$application = new Application();
$application->add($command);
// the second boolean argument tells if this is a single-command app
// 第二个布尔值参数,指明这是否是一个单一命令程序
$application->setDefaultCommand($command->getName(), true);
 
// this now executes the 'FooCommand' without passing its name
// 现在执行“FooCommand”时不需传入该命令的名称
$application->run();

简化了命令行的测试 

测试一个Symfony命令可谓是“不必要的复杂”,而且需要你深入到PHP的stream中。例如,你的测试需要模拟一个用户输入123foobar,那么你要用到下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Console\Tester\CommandTester;
 
$commandTester = new CommandTester($command);
$helper = $command->getHelper('question');
$helper->setInputStream($this->getInputStream("123\nfoo\nbar\n"));
 
protected function getInputStream($input)
{
    $stream = fopen('php://memory', 'r+', false);
    fputs($stream, $input);
    rewind($stream);
    return $stream;
}

在Symfony 3.2中,我们简化了命令测试,通过添加一个全新的setInputs()方法到CommandTester这个helper中。你只需把用户键入的“内容数组”传入即可:

1
2
3
4
use Symfony\Component\Console\Tester\CommandTester;
 
$commandTester = new CommandTester($command);
$commandTester->setInputs(['123', 'foo', 'bar']);