支付宝扫一扫付款
微信扫一扫付款
(微信为保护隐私,不显示你的昵称)
创建console命令时,一个最乏味的任务就是去处理命令的input和output的样式。显示标题和表格,或是让用户回答问题,总是会牵扯到大量的代码重复。
思考以下用于显示title的命令行例程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // src/AppBundle/Command/GreetCommand.php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class GreetCommand extends ContainerAwareCommand
{
// ...
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln(array(
'<info>Lorem Ipsum Dolor Sit Amet</>',
'<info>==========================</>',
'',
));
// ...
}
} |
显示一个简单的标题,需要三行代码,实现了改变字体颜色,对内容加下划线,以及在标题下方留一个空行。设计得当的命令行是需要应对样式的,但却令代码变得不必要的复杂。
为了减少那些样板一样的代码,Symfony命令提供了可选的 Symfony Style Guide。这些样式是通过一组helper method而实现的,助手方法允许创建 语义化 命令而毋须记住其样式。
在你的命令中,对 SymfonyStyle
类实例化,并把 $input
和 $output
变量做为其参数传入。然后,你就可以使用任意一个助手了,像是 title()
用于在命令行中显示标题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // src/AppBundle/Command/GreetCommand.php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class GreetCommand extends ContainerAwareCommand
{
// ...
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->title('Lorem Ipsum Dolor Sit Amet');
// ...
}
} |
SymfonyStyle
类定义了一些助手方法,覆盖了console命令行所需之常见互动。
title()
它把给定的字符串作为命令的标题显示。本方法在一个命令中注定只能使用一次,但并不妨碍你重复地使用它:
1 | $io->title('Lorem ipsum dolor sit amet'); |
section()
它把给定的字符串作为命令区段(command section)的标题显示。只在“希望把内容更好地分隔开”的复杂命令中才有这种需求:
1 2 3 4 5 6 7 | $io->section('Adding a User');
// ...
$io->section('Generating the Password');
// ... |
text()
它把给定的字符串或数组显示为常规文本。当用户使用命令时,它在输出帮助信息和操作方法时非常有用:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // use simple strings for short messages
// 使用简单字符串作为短消息
$io->text('Lorem ipsum dolor sit amet');
// ...
// consider using arrays when displaying long messages
// 当显示长信息时考虑使用数组
$io->text(array(
'Lorem ipsum dolor sit amet',
'Consectetur adipiscing elit',
'Aenean sit amet arcu vitae sem faucibus porta',
)); |
listing()
它把作为数组传入命令的元素,显示成无序清单:
1 2 3 4 5 | $io->listing(array(
'Element #1 Lorem ipsum dolor sit amet',
'Element #2 Lorem ipsum dolor sit amet',
'Element #3 Lorem ipsum dolor sit amet',
)); |
table()
它把给定的包含“headers和rows”的数组显示为紧凑表格:
newLine()
它在命令的output中显示空行。虽然看上去有用,但多数时候你根本不需要它。原因是每个helper都已经添加了自己的空行了,所以你不必特意关照垂直间距:
1 2 3 4 5 | // outputs a single blank line / 输出单个空行
$io->newLine();
// outputs three consecutive blank lines / 输出三个连续的空行
$io->newLine(3); |
note()
它把给定的字符串或字符串数组作为一个高亮的劝告显示出来。It displays the given string or array of strings as a highlighted admonition. 慎用此助手以避免将命令行搞乱:
1 2 3 4 5 6 7 8 9 10 11 12 | // use simple strings for short notes / 使用简单字符串以简短提醒
$io->note('Lorem ipsum dolor sit amet');
// ...
// consider using arrays when displaying long notes
// 当显示较长提示时,考虑使用数组
$io->note(array(
'Lorem ipsum dolor sit amet',
'Consectetur adipiscing elit',
'Aenean sit amet arcu vitae sem faucibus porta',
)); |
caution()
类似于 note()
助手,但内容更加显著地高亮。输出的内容类似于错误信息,所以除非必须,你应避免使用此助手。:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // use simple strings for short caution message
// 使用简单字符串以简短警告
$io->caution('Lorem ipsum dolor sit amet');
// ...
// consider using arrays when displaying long caution messages
// 当显示较长的警告信息时,考虑使用数组
$io->caution(array(
'Lorem ipsum dolor sit amet',
'Consectetur adipiscing elit',
'Aenean sit amet arcu vitae sem faucibus porta',
)); |
progressStart()
它显示一个带有的总步数的进度条 ,步数等同于传到方法中的参数(当不确定进度条的长度时,不要传入任何值):
1 2 3 4 5 6 7 | // displays a progress bar of unknown length
// 显示一个未知长度的进度条
$io->progressStart();
// displays a 100-step length progress bar
// 显示一个100步的进度条
$io->progressStart(100); |
progressAdvance()
它令进度条推进给定的步数 (或 1
步,如果没有参数传入的话):
1 2 3 4 5 | // advances the progress bar 1 step / 推进进度条1个step
$io->progressAdvance();
// advances the progress bar 10 steps / 推进进度条10步
$io->progressAdvance(10); |
progressFinish()
完成进度条的推进 (当进度条长度未知时,它完成全部剩余步数):
1 | $io->progressFinish(); |
ask()
它要求用户提供一些值:
1 | $io->ask('What is your name?'); |
你可以把默认值作为第二个参数传入,以便用户可以简单敲击
1 | $io->ask('Where are you from?', 'United States'); |
若你需要验证给定的值,把一个callback valicator作为第三个参数传入:
1 2 3 4 5 6 7 | $io->ask('Number of workers to start', 1, function ($number) {
if (!is_integer($number)) {
throw new \RuntimeException('You must type an integer.');
}
return $number;
}); |
askHidden()
它与 ask()
方法非常相似,但用户的输入将被隐藏,且无法定义一个默认值。使用它来问询敏感信息:
1 2 3 4 5 6 7 8 9 10 | $io->askHidden('What is your password?');
// validates the given answer
$io->askHidden('What is your password?', function ($password) {
if (empty($password)) {
throw new \RuntimeException('Password cannot be empty.');
}
return $password;
}); |
confirm()
它向用户询问的是一个 Yes/No 的问题,仅能返回 true
或 false
:
1 | $io->confirm('Restart the web server?'); |
你可以把默认值作为第二个参数传入,以便用户可以简单敲击
1 | $io->confirm('Restart the web server?', true); |
choice()
它所提问的问题,其答案被限定到一个给定的“有效答案列表”中:
1 | $io->choice('Select the queue to analyze', array('queue1', 'queue2', 'queue3')); |
你可以把默认值作为第二个参数传入,以便用户可以简单敲击
1 | $io->choice('Select the queue to analyze', array('queue1', 'queue2', 'queue3'), 'queue1'); |
success()
它把给定的字符串或字符串数组作为一个成功提示来高亮显示(带有绿色背景和 [OK]
标签)。它只能使用一次,用于显示所执行的命令之最终结果,但你可以在命令执行过程中重复地使用它:
1 2 3 4 5 6 7 8 9 10 11 12 | // use simple strings for short success messages
// 对简短的成功提示使用简单字符串
$io->success('Lorem ipsum dolor sit amet');
// ...
// consider using arrays when displaying long success messages
// 当成功提示较长时,考虑使用数组
$io->success(array(
'Lorem ipsum dolor sit amet',
'Consectetur adipiscing elit',
)); |
warning()
它把给定的字符串或字符串数组作为一个警告信息来高亮显示 (带有红色背景和 [WARNING]
标签))。它只能使用一次,用于显示所执行的命令之最终结果,但你可以在命令执行过程中重复地使用它:
1 2 3 4 5 6 7 8 9 10 11 12 | // use simple strings for short warning messages
// 对简短的警告信息使用简单字符串
$io->warning('Lorem ipsum dolor sit amet');
// ...
// consider using arrays when displaying long warning messages
// 当警告信息较长时,考虑使用数组
$io->warning(array(
'Lorem ipsum dolor sit amet',
'Consectetur adipiscing elit',
)); |
error()
它把给定的字符串或字符串数组作为一个错误信息来高亮显示 (带有红色背景和 [ERROR]
标签)。它只能使用一次,用于显示所执行的命令之最终结果,但你可以在命令执行过程中重复地使用它:
1 2 3 4 5 6 7 8 9 10 11 12 | // use simple strings for short error messages
// 对简短的错误信息使用简单字符串
$io->error('Lorem ipsum dolor sit amet');
// ...
// consider using arrays when displaying long error messages
// 当错误信息较长时,考虑使用数组
$io->error(array(
'Lorem ipsum dolor sit amet',
'Consectetur adipiscing elit',
)); |
如果你不喜欢Symfony风格的命令行设计,你可以定义自己的控制台风格组合。只要创建一个类去实现 StyleInterface
接口:
1 2 3 4 5 6 7 8 | namespace AppBundle\Console;
use Symfony\Component\Console\Style\StyleInterface;
class CustomStyle implements StyleInterface
{
// ...implement the methods of the interface / 实现接口中的方法
} |
然后,在命令中实例化这个自定义的类,而不是 SymfonyStyle
。 得益于 StyleInterface
,在改变命令外观时,你毋须改动命令的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | namespace AppBundle\Console;
use AppBundle\Console\CustomStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class GreetCommand extends ContainerAwareCommand
{
// ...
protected function execute(InputInterface $input, OutputInterface $output)
{
// Before / 之前
// $io = new SymfonyStyle($input, $output);
// After / 之后
$io = new CustomStyle($input, $output);
// ...
}
} |
本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。