fi1a / console
PHP 控制台命令。参数、选项和格式化
Requires
- php: ^7.3 || ^8
- ext-mbstring: *
- ext-posix: *
- fi1a/collection: ^2.0
- fi1a/dependency-injection: ^1.0
- fi1a/format: ^2.0
- fi1a/tokenizer: ^1.1
- fi1a/validation: ^2.0 || ^3.0
Requires (Dev)
- captainhook/captainhook: ^5.4
- phpunit/phpunit: ^9.3
- slevomat/coding-standard: ^6.3
- squizlabs/php_codesniffer: ^3.5
- vimeo/psalm: ^4.3
README
PHP 实现控制台命令和文本美化格式的库。
功能
- 命令自动支持 --help 来输出帮助信息;
- 支持一个或多个命令;
- 可以在命令中将传递的参数和选项值进行验证(检查);
- 控制台中的颜色格式化;
- 实现表格、列表、树等组件;
安装
可以使用 Composer 将此包作为依赖项安装。
composer require fi1a/console
依赖注入
来自包 fi1a/dependency-injection 的依赖注入容器
在依赖注入容器中,接口可用以下定义
- Fi1a\Console\IO\InputArgumentsInterface;
- Fi1a\Console\IO\FormatterInterface;
- Fi1a\Console\IO\ConsoleOutputInterface;
- Fi1a\Console\IO\InputInterface;
- Fi1a\Console\IO\InteractiveInputInterface;
- Fi1a\Console\Component\GroupComponent\GroupStyleInterface;
- Fi1a\Console\Component\GroupComponent\GroupComponentInterface;
- Fi1a\Console\Component\ListComponent\ListStyleInterface;
- Fi1a\Console\Component\ListComponent\ListComponentInterface;
- Fi1a\Console\Component\PaginationComponent\PaginationStyleInterface;
- Fi1a\Console\Component\PaginationComponent\PaginationComponentInterface;
- Fi1a\Console\Component\PanelComponent\PanelStyleInterface;
- Fi1a\Console\Component\PanelComponent\PanelComponentInterface;
- Fi1a\Console\Component\ProgressbarComponent\ProgressbarStyleInterface;
- Fi1a\Console\Component\ProgressbarComponent\ProgressbarComponentInterface;
- Fi1a\Console\Component\SpinnerComponent\SpinnerStyleInterface;
- Fi1a\Console\Component\SpinnerComponent\SpinnerComponentInterface;
- Fi1a\Console\Component\TableComponent\TableStyleInterface;
- Fi1a\Console\Component\TableComponent\TableComponentInterface;
- Fi1a\Console\Component\TreeComponent\TreeStyleInterface;
- Fi1a\Console\Component\TreeComponent\TreeComponentInterface;
di()->get(Fi1a\Console\IO\ConsoleOutputInterface::class)->writeln('Вывод в консоль');
使用
控制台中的命令、参数和选项
类 Fi1a\Console\App
提供了一个方便的接口来添加命令和启动应用程序。
命令
命令应该实现接口 Fi1a\Console\CommandInterface
。以下是一个简单命令的示例。
declare(strict_types=1); namespace Foo\Bar; /** * Простая команда */ class BazCommand extends AbstractCommand { /** * @inheritDoc */ public function __construct(DefinitionInterface $definition) { $definition->addOption('time', 't') ->default(false) ->description('Вывод времени.') ->validation() ->allOf() ->boolean(); $definition->addArgument('format') ->default('H:i:s') ->description('Формат вывода времени.'); } /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $output->writeln('<option=bold>Пример команды</>'); if ($definition->getOption('time')->getValue()) { $output->writeln( '<success>Серверное время: <option=bold>{{time}}</></success>', ['time' => date($definition->getArgument('format')->getValue())] ); } return 0; } /** * @inheritDoc */ public function description(): ?string { return 'Тестовая команда baz.'; } }
在这个例子中,我们在命令的构造函数中添加了选项 time
和参数 format
。启动命令后,会检查是否传入了 time
选项,如果传入,则输出指定格式 format
的服务器时间。如果没有传入格式,方法 getValue
将通过方法 default
返回默认值。
run
方法,在命令启动时作为参数传递
InputArgumentsInterface $input
- 输入参数和选项;ConsoleOutputInterface $output
- 控制台输出;InputInterface $stream
- 控制台输入流;DefinitionInterface $definition
- 访问声明的参数和选项;AppInterface $app
-Fi1a\Console\App
类的实例,该实例触发了该命令。
使用选项和参数
run
方法中传递的 DefinitionInterface $definition
对象,可以用来访问选项和参数的值。
$definition->getOption('time')->getValue(); $definition->getArgument('format')->getValue();
- 选项通过 --name=value 完整名称或 -s value 短代码传递;
- 参数作为字符串传递,由空格分隔。
启动控制台应用程序
要使用应用程序,需要调用方法 run
。方法 run
执行以下操作
- 分析 $argv 参数以确定命令;
- 验证选项和参数;
- 配置命令;
- 执行命令。
启动一个特定命令。以下代码将启动命令 \Foo\Bar\BazCommand
。
declare(strict_types=1); use Fi1a\Console\App; $code = (new App()) ->run(\Foo\Bar\BazCommand::class); exit($code);
启动多个命令,在第一个参数中指定。如果第一个参数是命令的名称 php foo.php qux
,则将启动命令 \Foo\Bar\QuxCommand
。
declare(strict_types=1); use Fi1a\Console\App; $code = (new App()) ->addCommand('baz', \Foo\Bar\BazCommand::class) ->addCommand('qux', \Foo\Bar\QuxCommand::class) ->run(); exit($code);
命令列表
调用没有参数或仅带参数 info 的脚本,将显示可用命令列表。示例
php foo.php
或 php foo.php info
命令描述来自 description
方法的返回值。
显示帮助信息
如果调用带参数 --help 的命令(php foo.php baz --help
),可以查看以下命令帮助信息
命令描述来自 description
方法的返回值。
显示错误信息
假设你调用示例 php foo.php baz -t j
$definition->addOption('time', 't') ->default(false) ->description('Вывод времени.') ->validation() ->allOf() ->boolean(); $definition->addArgument('format') ->default('H:i:s') ->description('Формат вывода времени.');
将看到以下错误信息
验证通过包 fi1a/validation 实现。所有验证规则均可用。
$definition->addOption('option1') ->validation() ->allOf() ->required() ->min(10) ->max(20); $argument = $definition->addArgument('argument1') ->multiple(); $argument->multipleValidation() ->allOf() ->array() ->required() ->minCount(2); $argument->validation() ->allOf() ->required() ->min(10) ->max(20);
validation
方法 - 验证单个值的规则;multipleValidation
方法 - 验证多个值的规则。
格式化
颜色方案(控制台颜色板)
提供三种颜色方案
- ANSI(4位颜色);
- 扩展(8位颜色);
- 真彩色(1670万)。
启动示例以显示颜色板
php examples/examples.php colors
控制台输出
使用控制台输出中的颜色,您可以格式化不同的输出类型(错误、标题、注释等)。
使用颜色样式
在输出时可以使用标签来着色显示的文本。
... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $output->writeln('<info>foo</info>'); $output->writeln('<error>bar</error>'); $output->writeln('<success>baz<info>qux</info></success>'); } ...
使用容器的示例
use Fi1a\Console\IO\ConsoleOutputInterface; $output = di()->get(ConsoleOutputInterface::class); $output->writeln('<info>foo</info>'); $output->writeln('<error>bar</error>'); $output->writeln('<success>baz<info>qux</info></success>');
以下为预定义样式
- error;
- success;
- info;
- comment;
- question;
- notice.
可以使用 Fi1a\Console\IO\Formatter
类的 addStyle
方法定义自己的样式。
use Fi1a\Console\IO\Formatter; use Fi1a\Console\IO\Style\TrueColor; use Fi1a\Console\IO\Style\TrueColorStyle; Formatter::addStyle('error', new TrueColorStyle(TrueColor::WHITE, TrueColor::RED));
TrueColor 方案支持任何十六进制颜色。此外,还支持通过 Fi1a\Console\IO\Style\ColorInterface
接口常量定义的命名颜色(ColorInterface::BLACK
、ColorInterface::RED
、ColorInterface::GREEN
等)。
如果终端不支持 TrueColor 或扩展,则使用最近的 ANSI 颜色。
提供格式化参数:blink、bold、conceal、reverse、underscore。您可以直接在标签内设置颜色、背景和参数。支持样式嵌套。
... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $output->writeln('<color=black>foo</>'); $output->writeln('<bg=white;color=black>bar</>'); $output->writeln('<color=red>baz<option=bold,underscore>qux</></>'); } ...
启动示例以显示格式化输出
php examples/examples.php output
控制台流输入
通过类 InputInterface $stream
的 read
方法读取(输入)控制台。
... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $value = $stream->read('y'); } ...
使用容器的示例
use Fi1a\Console\IO\InputInterface; $stream = di()->get(InputInterface::class); $value = $stream->read('y');
控制台交互输入
使用类 Fi1a\Console\IO\InteractiveInput
,可以添加要读取的控制台值,并访问输入的值。使用 addValue
方法添加要读取的控制台值。与参数和选项一样,可以访问来自包 fi1a/validation 的值验证器。
use Fi1a\Console\IO\InteractiveInput; ... /** * @inheritDoc * @psalm-suppress PossiblyFalseReference * @psalm-suppress MixedMethodCall */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $output->writeln(['', '<option=bold>Интерактивный ввод</>', '']); $interactive = new InteractiveInput($output, $stream); $interactive->addValue('foo') ->description('Введите количество от 1 до 10') ->validation() ->allOf() ->min(1) ->max(10); $bar = $interactive->addValue('bar') ->description('Введите строки длиной от 2-х символов') ->multiple(); $bar->multipleValidation() ->allOf() ->minCount(1) ->required(); $bar->validation() ->allOf() ->minLength(2); $interactive->addValue('baz') ->description('Согласны (y/n)') ->validation() ->allOf() ->boolean(); $interactive->read(); // Доступ к введенным значениям $output->writeln((string) $interactive->getValue('foo')->getValue()); $output->writeln((string) count((array) $interactive->getValue('bar')->getValue())); $output->writeln((string) $interactive->getValue('baz')->getValue()); return 0; } ...
使用容器的示例
use Fi1a\Console\IO\ConsoleOutputInterface; use Fi1a\Console\IO\InteractiveInputInterface; $output = di()->get(ConsoleOutputInterface::class); $interactive = di()->get(InteractiveInputInterface::class); $output->writeln(['', '<option=bold>Интерактивный ввод</>', '']); $interactive->addValue('foo') ->description('Введите количество от 1 до 10') ->validation() ->allOf() ->min(1) ->max(10); $bar = $interactive->addValue('bar') ->description('Введите строки длиной от 2-х символов') ->multiple(); $bar->multipleValidation() ->allOf() ->minCount(1) ->required(); $bar->validation() ->allOf() ->minLength(2); $interactive->addValue('baz') ->description('Согласны (y/n)') ->validation() ->allOf() ->boolean(); $interactive->read(); // Доступ к введенным значениям $output->writeln((string) $interactive->getValue('foo')->getValue()); $output->writeln((string) count((array) $interactive->getValue('bar')->getValue())); $output->writeln((string) $interactive->getValue('baz')->getValue());
启动示例以进行交互式输入
php examples/examples.php interactive
组件
面板组件
要绘制文本周围的边框或设置对齐方式,请使用 Fi1a\Console\Component\PanelComponent\PanelComponent
。面板组件可以嵌套。
use Fi1a\Console\Component\PanelComponent\PanelComponent; use Fi1a\Console\Component\PanelComponent\PanelStyle; use Fi1a\Console\Component\PanelComponent\PanelStyleInterface; use Fi1a\Console\IO\Style\ColorInterface; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $panelStyle = new PanelStyle(); $panelStyle->setWidth(40) ->setPadding(1) ->setBorder('heavy') ->setBackgroundColor(ColorInterface::YELLOW) ->setBorderColor(ColorInterface::RED) ->setColor(ColorInterface::BLACK) ->setAlign(PanelStyleInterface::ALIGN_CENTER); $panel = new PanelComponent( $output, 'Lorem ipsum dolor sit amet, <error>consectetur adipiscing elit</error>, ' . 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', $panelStyle ); $panel->display(); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\PanelComponent\PanelComponentInterface; use Fi1a\Console\Component\PanelComponent\PanelStyleInterface; use Fi1a\Console\IO\Style\ColorInterface; $panel = di()->get(PanelComponentInterface::class); $panelStyle = $panel->getStyle(); $panelStyle->setWidth(40) ->setPadding(1) ->setBorder('heavy') ->setBackgroundColor(ColorInterface::YELLOW) ->setBorderColor(ColorInterface::RED) ->setColor(ColorInterface::BLACK) ->setAlign(PanelStyleInterface::ALIGN_CENTER); $panel->setText('Lorem ipsum dolor sit amet, <error>consectetur adipiscing elit</error>, ' . 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'); $panel->display();
启动示例以显示面板
php examples/examples.php panel
可以通过设置以下值之一来更改面板边框样式
- ascii;
- double;
- heavy;
- horizontals;
- rounded.
启动示例以显示面板边框样式
php examples/examples.php panel-borders
可以使用 Fi1a\Console\Component\PanelComponent\BorderRegistry
类的 add
方法定义自己的边框样式。边框样式类必须实现 Fi1a\Console\Component\PanelComponent\BorderInterface
接口。
use Fi1a\Console\Component\PanelComponent\AsciiBorder; use Fi1a\Console\Component\PanelComponent\BorderRegistry; BorderRegistry::add( 'ascii', new AsciiBorder() );
组组件
要使面板具有相同的宽度和在同一行上排列,可以使用组组件。
use Fi1a\Console\Component\GroupComponent\GroupComponent; use Fi1a\Console\Component\GroupComponent\GroupStyle; use Fi1a\Console\Component\PanelComponent\PanelComponent; use Fi1a\Console\Component\PanelComponent\PanelStyle; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $groupStyle = new GroupStyle(40); $groupStyle->setPanelSpacing(2); $group = new GroupComponent($output, $groupStyle); $panelStyle = new PanelStyle(); $panelStyle->setBorder('heavy') ->setPadding(1); $panel1 = new PanelComponent( $output, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, ' . 'sed do eiusmod tempor incididunt ut ' . 'labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ' . 'nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit ' . 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' . 'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', $panelStyle ); $panel2 = new PanelComponent( $output, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, ' . 'sed do eiusmod tempor incididunt ut ' . 'labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ' . 'nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit ' . 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur.', $panelStyle ); $panel3 = new PanelComponent( $output, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, ' . 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', $panelStyle ); $group->addPanel($panel1); $group->addPanel($panel2); $group->addPanel($panel3); $group->display(); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\GroupComponent\GroupComponentInterface; use Fi1a\Console\Component\PanelComponent\PanelComponentInterface; use Fi1a\Console\Component\PanelComponent\PanelStyleInterface; $group = di()->get(GroupComponentInterface::class); $group->getStyle()->setPanelSpacing(2); $panelStyle = di()->get(PanelStyleInterface::class); $panelStyle->setBorder('heavy') ->setPadding(1); $panel1 = di()->get(PanelComponentInterface::class); $panel1->setStyle($panelStyle); $panel1->setText('Lorem ipsum dolor sit amet, consectetur adipiscing elit, ' . 'sed do eiusmod tempor incididunt ut ' . 'labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ' . 'nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit ' . 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' . 'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'); $panel2 = di()->get(PanelComponentInterface::class); $panel2->setStyle($panelStyle); $panel2->setText('Lorem ipsum dolor sit amet, consectetur adipiscing elit, ' . 'sed do eiusmod tempor incididunt ut ' . 'labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ' . 'nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit ' . 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'); $panel3 = di()->get(PanelComponentInterface::class); $panel3->setStyle($panelStyle); $panel3->setText('Lorem ipsum dolor sit amet, consectetur adipiscing elit, ' . 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'); $group->addPanel($panel1); $group->addPanel($panel2); $group->addPanel($panel3); $group->display();
启动示例以显示面板组
php examples/examples.php group
列表组件
用于显示列表的组件为 Fi1a\Console\Component\ListComponent\ListComponent
。支持嵌套列表。
use Fi1a\Console\Component\ListComponent\ListComponent; use Fi1a\Console\Component\ListComponent\ListStyle; use Fi1a\Console\Component\ListComponent\ListStyleInterface; use Fi1a\Console\IO\Style\ColorInterface; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $listStyle = new ListStyle(); $listStyle->setType('upper-alpha') ->setMarkerColor(ColorInterface::GREEN); $subListStyle = new ListStyle(); $subListStyle->setType('lower-alpha') ->setMarkerColor(ColorInterface::RED) ->setPosition(ListStyleInterface::POSITION_OUTSIDE); $subList = new ListComponent($output, $subListStyle); $subList->addItem('Lorem ipsum dolor sit amet'); $subList->addItem('Consectetur adipiscing elit'); $list = new ListComponent($output, $listStyle); $list->addItem('Lorem ipsum dolor sit amet'); $list->addItem('Consectetur adipiscing elit'); $list->addItem($subList); $list->addItem('Sed do eiusmod tempor incididunt'); $list->addItem('Duis aute irure dolor in reprehenderit'); $list->addItem('Reprehenderit in voluptate velit'); $list->display(); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\ListComponent\ListComponentInterface; use Fi1a\Console\Component\ListComponent\ListStyleInterface; use Fi1a\Console\IO\Style\ColorInterface; $subList = di()->get(ListComponentInterface::class); $subList->getStyle() ->setType('lower-alpha') ->setMarkerColor(ColorInterface::RED) ->setPosition(ListStyleInterface::POSITION_OUTSIDE); $subList->addItem('Lorem ipsum dolor sit amet'); $subList->addItem('Consectetur adipiscing elit'); $list = di()->get(ListComponentInterface::class); $list->getStyle() ->setType('upper-alpha') ->setMarkerColor(ColorInterface::GREEN); $list->addItem('Lorem ipsum dolor sit amet'); $list->addItem('Consectetur adipiscing elit'); $list->addItem($subList); $list->addItem('Sed do eiusmod tempor incididunt'); $list->addItem('Duis aute irure dolor in reprehenderit'); $list->addItem('Reprehenderit in voluptate velit'); $list->display();
可以使用列表样式类的 setType
方法设置标记类型。
以下为支持的标记类型
- upper-alpha - 大写字母列表 (A, B, C, D, E, …);
- square - 用作标记的是正方形;
- lower-alpha - 小写字母列表 (a, b, c, d, e, …);
- decimal-leading-zero - 带前导零的序号 (01, 02, 03, 04, 05, …);
- decimal - 序号 (1, 2, 3, 4, 5, …);
- circle - 用作标记的是空心圆圈;
- disc - 用作列表元素的标记的是实心圆圈。
启动列表示例
php examples/examples.php list
可以使用 Fi1a\Console\Component\ListComponent\ListTypeRegistry
类的 add
方法定义自己的列表标记类型。列表标记类型类必须实现 Fi1a\Console\Component\ListComponent\ListTypeInterface
接口。
use Fi1a\Console\Component\ListComponent\ListTypeRegistry; use Fi1a\Console\Component\ListComponent\UpperAlphaListType; ListTypeRegistry::add('upper-alpha', new UpperAlphaListType());
分页导航组件
如果需要分页显示输出,可以使用分页导航组件。
示例
use Fi1a\Console\Component\PaginationComponent\PaginationComponent; use Fi1a\Console\Component\PaginationComponent\PaginationStyle; use Fi1a\Console\Component\TableComponent\TableComponent; use Fi1a\Console\Component\TableComponent\TableStyle; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $data = [ ['Смартфон', '1000', '2', '2000'], ['Шкаф', '500', '1', '500'], ['Электробритва', '300', '5', '1500'], ['Станок', '200', '1', '200'], ['Диван', '1200', '1', '1200'], ['Кровать', '100', '2', '200'], ['Кресло', '300', '3', '900'], ['Шифанер', '150', '1', '150'], ['Стул', '50', '4', '200'], ['Стол', '100', '1', '100'], ]; $tableStyle = new TableStyle(); $table = new TableComponent($output, $tableStyle); $table->setHeaders(['Товар', 'Стоимость', 'Количество', 'Итоговая сумма']); $paginationStyle = new PaginationStyle(); $pagination = new PaginationComponent($output, $stream, $paginationStyle); $pagination->setCount((int) ceil(count($data) / 3)); $page = 1; do { $rows = array_slice($data, ($page - 1) * 3, 3); $table->setRows($rows); $table->display(); $pagination->display(); $page = $pagination->getCurrent(); } while ($pagination->isValid()); $output->writeln(''); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\PaginationComponent\PaginationComponentInterface; use Fi1a\Console\Component\TableComponent\TableComponentInterface; use Fi1a\Console\IO\ConsoleOutputInterface; $data = [ ['Смартфон', '1000', '2', '2000'], ['Шкаф', '500', '1', '500'], ['Электробритва', '300', '5', '1500'], ['Станок', '200', '1', '200'], ['Диван', '1200', '1', '1200'], ['Кровать', '100', '2', '200'], ['Кресло', '300', '3', '900'], ['Шифанер', '150', '1', '150'], ['Стул', '50', '4', '200'], ['Стол', '100', '1', '100'], ]; $output = di()->get(ConsoleOutputInterface::class); $table = di()->get(TableComponentInterface::class); $table->setHeaders(['Товар', 'Стоимость', 'Количество', 'Итоговая сумма']); $pagination = di()->get(PaginationComponentInterface::class); $pagination->setCount((int) ceil(count($data) / 3)); $page = 1; do { $rows = array_slice($data, ($page - 1) * 3, 3); $table->setRows($rows); $table->display(); $pagination->display(); $page = $pagination->getCurrent(); } while ($pagination->isValid()); $output->writeln('');
启动带有分页导航的示例
php examples/examples.php pagination
Progressbar 组件
在执行长时间命令时,显示进度信息非常有用。
要显示进度信息,请使用 Fi1a\Console\Component\ProgressbarComponent\ProgressbarComponent
。
use Fi1a\Console\Component\ProgressbarComponent\ProgressbarComponent; use Fi1a\Console\Component\ProgressbarComponent\ProgressbarStyle; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $progressbarStyle = new ProgressbarStyle(); $progressbarStyle->setTemplateByName('full'); $progressbar = new ProgressbarComponent($output, $progressbarStyle); $progressbar->start(10); do { $progressbar->increment(); $progressbar->display(); sleep(1); } while($progressbar->getProgress() < $progressbar->getMaxSteps()); $progressbar->finish(); $output->writeln(['', '']); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\ProgressbarComponent\ProgressbarComponentInterface; use Fi1a\Console\IO\ConsoleOutputInterface; $output = di()->get(ConsoleOutputInterface::class); $progressbar = di()->get(ProgressbarComponentInterface::class); $progressbar->getStyle() ->setTemplateByName('full'); $progressbar->start(10); do { $progressbar->increment(); $progressbar->display(); sleep(1); } while($progressbar->getProgress() < $progressbar->getMaxSteps()); $progressbar->finish(); $output->writeln(['', '']);
使用 setTemplateByName
方法可以设置预定义模板之一。
- 短模板 (
[{{bar}}]
); - 正常模板 (
{{current}}/{{max}} [{{bar}}] {{percent|sprintf("3s")}}%{{if(title)}} {{title}}{{endif}}
); - 时间模板 (
[{{bar}}] {{elapsed|sprintf("10s")}} / {{remaining|sprintf("-10s")}}{{if(title)}} {{title}}{{endif}}
); - 内存模板 (
[{{bar}}] {{memory|memory}}{{if(title)}} {{title}}{{endif}}
); - 完整模板 (
{{current}}/{{max}} [{{bar}}] {{percent|sprintf("3s")}}% {{elapsed|sprintf("10s")}} / {{remaining|sprintf("-10s")}} {{memory|memory}}{{if(title)}} {{title}}{{endif}}
).
您可以使用 Fi1a\Console\Component\ProgressbarComponent\ProgressbarTemplateRegistry
类的 add
方法添加自己的模板。
use Fi1a\Console\Component\ProgressbarComponent\ProgressbarTemplateRegistry; ProgressbarTemplateRegistry::add( 'normal', '{{current}}/{{max}} [{{bar}}] {{percent|sprintf("3s")}}%{{if(title)}} {{title}}{{endif}}' );
启动带有 progressbar 的示例
php examples/examples.php progressbar
Spinner 组件
功能
- 旋转时的标题;
- 支持模板 (
{{if(title)}}{{title}} {{endif}}<color=green>{{spinner}}</>
); - 具有
clear
方法; - 不同的外观和添加自定义 spinner 的能力。
Spinner 的外观
- 点状;
- 线条;
- 垂直增长;
- 水平增长;
- 条状。
您可以使用 Fi1a\Console\Component\SpinnerComponent\SpinnerRegistry
类的 add
方法添加自己的 spinner。添加的 spinner 必须实现 Fi1a\Console\Component\SpinnerComponent\SpinnerInterface
接口。
use Fi1a\Console\Component\SpinnerComponent\DotsSpinner; use Fi1a\Console\Component\SpinnerComponent\SpinnerRegistry; SpinnerRegistry::add('dots', new DotsSpinner());
示例
use Fi1a\Console\Component\SpinnerComponent\SpinnerComponent; use Fi1a\Console\Component\SpinnerComponent\SpinnerStyle; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $spinnerStyle = new SpinnerStyle(); $spinnerStyle->setTemplate('{{if(title)}}{{title}} {{endif}}<color=green>{{spinner}}</> '); $spinner = new SpinnerComponent($output, $spinnerStyle); $index = 0; do { if ($index % 1000000 === 0) { $title = $spinner->getTitle(); if ($title) { $spinner->clear(); $output->writeln($title); } $spinner->setTitle('In progress (' . $index . ')'); } $spinner->display(); $index++; } while ($index < 10000000); $output->writeln(''); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\SpinnerComponent\SpinnerComponentInterface; use Fi1a\Console\IO\ConsoleOutputInterface; $output = di()->get(ConsoleOutputInterface::class); $spinner = di()->get(SpinnerComponentInterface::class); $spinner->getStyle() ->setTemplate('{{if(title)}}{{title}} {{endif}}<color=green>{{spinner}}</> '); $index = 0; do { if ($index % 1000000 === 0) { $title = $spinner->getTitle(); if ($title) { $spinner->clear(); $output->writeln($title); } $spinner->setTitle('In progress (' . $index . ')'); } $spinner->display(); $index++; } while ($index < 10000000); $output->writeln('');
启动示例
php examples/examples.php spinner
表格组件
Fi1a\Console\Component\TableComponent\TableComponent
类用于在终端上显示表格数据。
要显示表格,创建一个 Fi1a\Console\Component\TableComponent\TableComponent
对象,使用 setHeaders
添加标题,使用 setRows
添加行,然后使用 display
方法输出到控制台。
use Fi1a\Console\Component\TableComponent\TableComponent; use Fi1a\Console\Component\TableComponent\TableStyle; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $headers = ['Товар', 'Стоимость', 'Количество', 'Итоговая сумма']; $rows = [ ['Смартфон', '1000', '2', '2000'], ['Шкаф', '500', '1', '500'], ]; $tableStyle = new TableStyle(); $tableStyle->setBorder('ascii') ->setWidth(50); $table = new TableComponent($output, $tableStyle); $table->setHeaders($headers); $table->setRows($rows); $table->display(); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\TableComponent\TableComponentInterface; $headers = ['Товар', 'Стоимость', 'Количество', 'Итоговая сумма']; $rows = [ ['Смартфон', '1000', '2', '2000'], ['Шкаф', '500', '1', '500'], ]; $table = di()->get(TableComponentInterface::class); $table->getStyle() ->setBorder('ascii') ->setWidth(50); $table->setHeaders($headers); $table->setRows($rows); $table->display();
如果未设置表格宽度,则列宽将根据单元格内容计算。
单元格属性
- value - 值;
- colspan - 单元格跨越的列数;
- style -
Fi1a\Console\Component\TableComponent\TableCellStyleInterface
风格。
use Fi1a\Console\Component\TableComponent\TableCell; use Fi1a\Console\Component\TableComponent\TableCellStyle; use Fi1a\Console\Component\TableComponent\TableCellStyleInterface; $style = new TableCellStyle(); $style->setAlign(TableCellStyleInterface::ALIGN_CENTER) $cell = new TableCell([ 'value' => 'foo', 'colspan' => 2, 'style' => $style, ]);
您可以使用 setBorder
方法设置表格边框样式,指定以下值之一:Fi1a\Console\Component\TableComponent\TableStyle
对象的方法
- none;
- ascii;
- ascii_compact;
- double;
- double_compact;
- heavy;
- heavy_compact;
- horizontals;
- rounded;
- rounded_compact.
启动示例
php examples/examples.php table
可以使用 Fi1a\Console\Component\TableComponent\BorderRegistry
类的 add
方法定义自己的边框样式。边框样式类必须实现 Fi1a\Console\Component\TableComponent\BorderInterface
接口。
use Fi1a\Console\Component\TableComponent\BorderRegistry; BorderRegistry::add('none', new NoneBorder());
显示树组件
Fi1a\Console\Component\TreeComponent\TreeComponent
类可以在终端中生成树形表示。树形结构是表示文件系统或其他任何层次结构数据的好方法。
use Fi1a\Console\Component\TreeComponent\TreeComponent; use Fi1a\Console\Component\TreeComponent\TreeStyle; ... /** * @inheritDoc */ public function run( InputArgumentsInterface $input, ConsoleOutputInterface $output, InputInterface $stream, DefinitionInterface $definition, AppInterface $app ): int { $style = new TreeStyle(); $style->setWidth(20) ->setLine('heavy'); $tree = new TreeComponent($output); $node1 = $tree->addNode('Lorem ipsum dolor', $style); $node1->addNode('Ex ea commodo consequat', $style); $node2 = $tree->addNode('Consectetur adipiscing elit', $style); $node3 = $node2->addNode('Ex ea commodo consequat', $style); $node2->addNode('Sunt in culpa qui officia', $style); $node3->addNode('Ut aliquip ex ea commodo'); $node3->addNode('Sunt in culpa qui officia'); $tree->addNode('Ut enim ad minim veniam', $style); $tree->display(); return 0; } ...
使用容器的示例
use Fi1a\Console\Component\TreeComponent\TreeComponentInterface; use Fi1a\Console\Component\TreeComponent\TreeStyleInterface; $style = di()->get(TreeStyleInterface::class); $style->setWidth(20) ->setLine('heavy'); $tree = di()->get(TreeComponentInterface::class); $tree->setStyle($style); $node1 = $tree->addNode('Lorem ipsum dolor', $style); $node1->addNode('Ex ea commodo consequat', $style); $node2 = $tree->addNode('Consectetur adipiscing elit', $style); $node3 = $node2->addNode('Ex ea commodo consequat', $style); $node2->addNode('Sunt in culpa qui officia', $style); $node3->addNode('Ut aliquip ex ea commodo'); $node3->addNode('Sunt in culpa qui officia'); $tree->addNode('Ut enim ad minim veniam', $style); $tree->display();
您可以使用 setLine
方法设置线条样式,指定以下值之一:Fi1a\Console\Component\TreeComponent\TreeStyle
对象的方法
- normal;
- double;
- heavy;
- ascii.
启动示例
php examples/examples.php tree
可以使用 add
方法来定义自己的线条样式,该方法属于 Fi1a\Console\Component\TreeComponent\LineRegistry
类。线条样式类需要实现 Fi1a\Console\Component\TreeComponent\LineInterface
接口。
use Fi1a\Console\Component\TreeComponent\LineRegistry; use Fi1a\Console\Component\TreeComponent\NormalLine; LineRegistry::add('normal', new NormalLine());