jbzoo/cli

该框架帮助创建CLI工具,并为symfony/console, symfony/process提供新工具。

7.2.2 2024-03-29 11:53 UTC

This package is auto-updated.

Last update: 2024-08-29 12:36:41 UTC


README

CI Coverage Status Psalm Coverage Psalm Level CodeFactor
Stable Version Total Downloads Dependents GitHub License

为什么?

该库极大地扩展了CLI应用程序的功能,并帮助在PHP中更快、更轻松地创建新的控制台工具。以下是为什么这个库是必需的总结:

  • 增强功能

    • 该库为Symfony/Console提供动力,简化了控制台工具的开发。
  • 进度条改进

    • 开发者可以获得一个针对循环操作优化的进度条,并增加了调试信息。这使得跟踪任务进度和诊断问题变得轻而易举。请参阅DemoProgressBar.php实时演示
    • 在CliCommand中将$this->_($messages, $level, $context)作为部分替换Symfony/Console中的$output->writeln()
    • cli($messages, $level, $context)作为不同类的别名。
    • 在CliCommand中将$this->progressBar(iterable|int $listOrMax, \Closure $callback, string $title = '')作为部分替换Symfony/Console ProgressBar。
  • 严格的类型转换

  • 样式和输出定制

    • 借助内置样式和颜色方案,开发者可以使他们的控制台输出更具可读性和视觉吸引力。请参阅DemoStyles.php
  • 消息别名

    • 该库引入了强大的消息输出别名,允许简洁、一致的命令调用。这在保持代码清洁方面特别有帮助。
  • 高级选项

    • 诸如性能分析、时间戳、错误静默和专用输出模式(如cron和logstash模式)等特性使开发者能够根据其特定需求细化其控制台输出和诊断。
    • 使用--profile选项显示时间和内存使用信息。
    • 使用--timestamp选项在每个消息的开头显示时间戳。
    • 禁用任何错误。所以退出码始终为0(如果可能)使用--mute-errors
    • 在带有--non-zero-on-error选项的情况下,任何非零退出码的StdErr消息。
    • 对于任何错误消息,应用程序将使用StdOut而不是StdErr --stdout-only选项(风险自负!)。
    • 使用--no-progress选项禁用日志的进度条动画。
  • 灵活的输出模式

    • 库提供不同的输出格式,以适应各种用例。无论是关注用户友好的文本、日志还是与ELK Stack等工具的集成,都有为您量身定制的输出模式。
    • --output-mode=text。默认情况下,文本输出格式。用户友好且易于阅读。
    • --output-mode=cron。它主要关注日志输出。它是--timestamp --profile --stdout-only --no-progress -vv --no-ansi的组合。
    • --output-mode=logstash。它主要关注ELK Stack的Logstash格式。这也意味着--stdout-only --no-progress -vv
  • 附加功能

    • 有一个多进程模式(请不要将其与多线程混淆),以加快对单调数据集的工作。
    • 交互式模式中的用户输入的辅助函数。

在线演示

输出常规消息

asciicast

进度条演示

asciicast

快速入门 - 构建你的第一个CLI应用程序

安装

composer require jbzoo/cli

最简单的CLI应用程序具有以下文件结构。有关更多详细信息,请参阅演示应用程序

文件结构

/path/to/app/
    my-app                      # Binrary file (See below)
    composer.json               # Composer file
    /Commands/                  # Commands directory
        Simple.php              # One of the commands (See below)
    /vendor/
        autoload.php            # Composer autoload

Composer文件

./demo/composer.json

查看详细信息
{
    "name"        : "vendor/my-app",
    "type"        : "project",
    "description" : "Example of CLI App based on JBZoo/CLI",
    "license"     : "MIT",
    "keywords"    : ["cli", "application", "example"],

    "require"     : {
        "php"       : ">=8.1",
        "jbzoo/cli" : "^7.1.0"
    },

    "autoload"    : {
        "psr-4" : {"DemoApp\\" : ""}
    },

    "bin"         : ["my-app"]
}

二进制文件

二进制文件:demo/my-app

查看详细信息
#!/usr/bin/env php
<?php declare(strict_types=1);

namespace DemoApp;

use JBZoo\Cli\CliApplication;

// Init composer autoloader
require_once __DIR__ . '/vendor/autoload.php';

// Optional. Set your application name and version.
$application = new CliApplication('My Console Application', 'v1.0.0');

// Optional. Looks at the online generator of ASCII logos
// https://patorjk.com/software/taag/#p=testall&f=Epic&t=My%20Console%20App
$application->setLogo(
  <<<'EOF'
        __  __          _____                      _
       |  \/  |        / ____|                    | |          /\
       | \  / |_   _  | |     ___  _ __  ___  ___ | | ___     /  \   _ __  _ __
       | |\/| | | | | | |    / _ \| '_ \/ __|/ _ \| |/ _ \   / /\ \ | '_ \| '_ \
       | |  | | |_| | | |___| (_) | | | \__ \ (_) | |  __/  / ____ \| |_) | |_) |
       |_|  |_|\__, |  \_____\___/|_| |_|___/\___/|_|\___| /_/    \_\ .__/| .__/
                __/ |                                               | |   | |
               |___/                                                |_|   |_|
      EOF,
);

// Scan directory to find commands.
//  * It doesn't work recursively!
//  * They must be inherited from the class \JBZoo\Cli\CliCommand
$application->registerCommandsByPath(__DIR__ . '/Commands', __NAMESPACE__);

// Optional. Action name by default (if there is no arguments)
$application->setDefaultCommand('list');

// Run application
$application->run();

简单的CLI操作

最简单的CLI操作:./demo/Commands/DemoSimple.php

查看详细信息
<?php declare(strict_types=1);

namespace DemoApp\Commands;

use JBZoo\Cli\CliCommand;
use JBZoo\Cli\Codes;

class Simple extends CliCommand
{
    protected function configure(): void
    {
        // Action name. It will be used in command line.
        // Example: `./my-app simple`
        $this->setName('simple');

        // Defined inhereted CLI options. See ./src/CliCommand.php for details.
        parent::configure();
    }

    protected function executeAction(): int
    {
        // Your code here
        $this->_('Hello world!');

        // Exit code. 0 - success, 1 - error.
        return self::SUCCESS;
    }
}

内置功能

清理输入变量

作为实时演示,请查看演示应用程序 - ./demo/Commands/DemoOptionsStrictTypes.php

尝试启动./my-app options-strict-types

// If the option has `InputOption::VALUE_NONE` it returns true/false.
// --option-name
$value = $this->getOpt('option-name'); // `$value === true` 

// --option-name="    123.6   "
$value = $this->getOpt('option-name'); // Returns the value AS-IS. `$value ===  "   123.6   "`

// --option-name="    123.6   "
$value = $this->getOptBool('option-name'); // Converts an input variable to boolean. `$value === true`

// --option-name="    123.6   "
$value = $this->getOptInt('option-name'); // Converts an input variable to integer. `$value === 123`
$value = $this->getOptInt('option-name', 42, [1, 2, 42]); // Strict comparing with allowed values

// --option-name="    123.6   "
$value = $this->getOptFloat('option-name'); // Converts an input variable to float. `$value === 123.6`
$value = $this->getOptFloat('option-name', 1.0, [1.0, 2.0, 3.0]); // Strict comparing with allowed values

// --option-name="    123.6   "
$value = $this->getOptString('option-name'); // Converts an input variable to trimmed string. `$value === "123.6"`
$value = $this->getOptString('option-name', 'default', ['default', 'mini', 'full']); // Strict comparing with allowed values

// --option-name=123.6
$value = $this->getOptArray('option-name'); // Converts an input variable to trimmed string. `$value === ["123.6"]`

// --option-name="15 July 2021 13:48:00"
$value = $this->getOptDatetime('option-name'); // Converts an input variable to \DateTimeImmutable object.

// Use standard input as input variable.
// Example. `echo " Qwerty 123 " | php ./my-app agruments`
$value = self::getStdIn(); // Reads StdIn as string value. `$value === " Qwerty 123 \n"`

以不同颜色和样式渲染文本

output-styles

有预定义的颜色列表

<black>  Text in Black color  </black>
<red>    Text in Red Color    </red>
<green>  Text in Green Color  </green>
<yellow> Text in Yellow Color </yellow>
<blue>   Text in Blue Color   </blue>
<magenta>Text in Magenta Color</magenta>
<cyan>   Text in Cyan Color   </cyan>
<white>  Text in White Color  </white>

<!-- Usually default color is white. It depends on terminal settings. -->
<!-- You should use it only to overwrite nested tags. -->
<default>Text in Default Color</default>

有预定义的样式列表

<bl>Blinked Text</bl>
<b>Bold Text</b>
<u>Underlined Text</u>
<r>Reverse Color/Backgroud</r>
<bg>Change Background Only</bg>

您还可以组合颜色和样式。

<magenta-bl>Blinked text in magenta color</magenta-bl>
<magenta-b>Bold text in magenta color</magenta-b>
<magenta-u>Underlined text in magenta color</magenta-u>
<magenta-r>Reverse text in magenta color</magenta-r>
<magenta-bg>Reverse only background of text in magenta color</magenta-bg>

还有Symfony Console标准样式的预定义快捷键

<i> alias for <info>
<c> alias for <commnet>
<q> alias for <question>
<e> alias for <error>

详细级别

控制台命令有不同的详细级别,这些详细级别决定了其输出中显示的消息。

作为实时演示,请查看演示应用程序 - ./demo/Commands/ExamplesOutput.php。您可以看到演示视频

使用详细级别的示例

output-full-example

// There two strictly(!) recommended output ways:

/**
 * Prints a message to the output in the command class which inherits from the class \JBZoo\Cli\CliCommand
 * 
 * @param string|string[] $messages     Output message(s). Can be an array of strings or a string. Array of strings will be imploded with new line.
 * @param string          $verboseLevel is one of value form the class \JBZoo\Cli\OutLvl::*
 * @param string          $context      is array of extra info. Will be serialized to JSON and displayed in the end of the message.
 */
$this->_($messages, $verboseLevel, $context);

/**
 * This is global alias function of `$this->_(...)`.
 * It's nice to have it if you want to display a text from not CliCommand class.
 */
JBZoo\Cli\cli($messages, $verboseLevel, $context);
 
# Do not output any message
./my-app output -q
./my-app output --quiet

# Normal behavior, no option required. Only the most useful messages.
./my-app output 

# Increase verbosity of messages
./my-app output -v

# Display also the informative non essential messages
./my-app output -vv

# Display all messages (useful to debug errors)
./my-app output -vvv

内存和时间分析

作为实时演示,请查看演示应用程序 - ./demo/Commands/DemoProfile.php

尝试启动./my-app profile --profile

profiling

进度条

作为实时演示,请查看演示应用程序 - ./demo/Commands/DemoProgressBar.php实时演示

您可以将此视为要分析的长循环的替代品。

请注意,在--verbose模式下,计算所有额外的调试信息会在内存和运行时产生额外的开销。

简单示例

progress-default-example

$this->progressBar(5, function (): void {
    // Some code in loop
});

高级用法

progress-full-example

$this->progressBar($arrayOfSomething, function ($value, $key, $step) {
    // Some code in loop

    if ($step === 3) {
        throw new ExceptionBreak("Something went wrong with \$value={$value}. Stop the loop!");
    }

    return "<c>Callback Args</c> \$value=<i>{$value}</i>, \$key=<i>{$key}</i>, \$step=<i>{$step}</i>";
}, 'Custom messages based on callback arguments', $throwBatchException);

辅助函数

作为实时演示,请查看演示应用程序 - ./demo/Commands/DemoHelpers.php

尝试启动./my-app helpers

JBZoo/Cli使用Symfony Question Helper作为别名的基。

helpers

常见问题

提出任何自定义问题,等待用户的输入。您可以设置默认值。

$yourName = $this->ask("What's your name?", 'Default Noname');
$this->_("Your name is \"{$yourName}\"");

询问用户的密码

提出一个问题并隐藏响应。这对于密码特别方便。您可以设置随机值作为默认值。

$yourSecret = $this->askPassword("New password?", true);
$this->_("Your secret is \"{$yourSecret}\"");

让用户选择选项

如果您有一个用户可以选择的预定义答案集,可以使用 askOption 方法,确保用户只能从预定义列表中输入有效的字符串。可以选择设置默认选项(索引或字符串)。

$selectedColor = $this->askOption("What's your favorite color?", ['Red', 'Blue', 'Yellow'], 'Blue');
$this->_("Selected color is {$selectedColor}");

表示是/否问题

假设您想在执行实际操作之前确认操作。请将以下内容添加到您的命令中。

$isConfirmed = $this->confirmation('Are you ready to execute the script?');
$this->_("Is confirmed: " . ($isConfirmed ? 'Yes' : 'No'));

渲染键=>值列表

如果您需要显示对齐的列表,请使用以下代码。

use JBZoo\Cli\CliRender;

$this->_(CliRender::list([
    "It's like a title",
    'Option Name' => 'Option Value',
    'Key' => 'Value',
    'Another Key #2' => 'Qwerty',
], '*')); // It's bullet character
 * It's like a title
 * Option Name   : Option Value
 * Key           : Value
 * Another Key #2: Qwerty

易于记录

简单日志

./my-app output --timestamp >> /path/to/crontab/logs/$(date +%Y-%m-%d).log 2>&1

logs-simple

计划任务

只需添加 --output-mode=cron 标志,并将输出保存到文件。特别是,这对于保存 Crontab 的日志非常方便。

./my-app output --output-mode=cron >> /path/to/crontab/logs/$(date +%Y-%m-%d).log 2>&1

logs-cron

Elasticsearch / Logstash (ELK)

只需添加 --output-mode=logstash 标志,并将输出保存到文件。特别是,这对于保存 ELK Stack 的日志非常方便。

./my-app output --output-mode=logstash >> /path/to/logstash/logs/$(date +%Y-%m-%d).log 2>&1

logs-logstash-exception

多进程

存在一种多进程模式(请勿将其与多线程混淆),用于加快与单调数据集的工作速度。基本上,JBZoo\Cli 将为每个数据集启动一个独立的子进程(不是线程!)并等待它们全部执行(就像 Promise 一样)。这就是您获得加速的方式,这取决于您服务器的性能和数据处理的算法。

您将看到一个简单的进度条,但您无法像在正常模式下那样进行性能分析和日志记录。

示例请在此处查找

注意

  • 请注意 executeOneProcess()getListOfChildIds() 方法,这些方法用于管理子进程。它们是从 CliCommandMultiProc 类继承的。
  • 最佳子进程数量是 CPU 核心数 - 1。您可以通过设置 CLI 选项来覆盖此值。有关详细信息,请参阅此处 ./src/CliCommandMultiProc.php
  • 请务必注意并发。调试起来并不容易。请尝试使用 -vvv 选项查看所有错误和警告。

技巧与窍门

  • 使用类 \JBZoo\Cli\Codes 获取所有可用的退出代码。
  • 您可以为任何消息添加额外的上下文。它将被序列化为 JSON 并显示在消息的末尾。只需使用 CliHelper::getInstance()->appendExtraContext(['section' => ['var' => 'value']]);
  • 您可以将常量 \JBZOO_CLI_TIMESTAMP_REAL=true 定义为添加 timestamp_real 作为额外上下文。有时这对于 Logstash 很有用,如果默认值 @timestamp 对您不起作用。

贡献

# Fork the repo and build project
make update

# Make your local changes

# Run all tests and check code style
make test-all

# Create your pull request and check all tests on GithubActions page

有用的项目和链接

许可证

MIT

另请参阅

  • CI-Report-Converter - 转换不同的错误报告,以与流行的 CI 系统深度兼容。
  • Composer-Diff - 查看 composer update 后已更改的包。
  • Composer-Graph - 基于 mermaid-js 的 composer.json 依赖关系图可视化。
  • Mermaid-PHP - 使用 mermaid 脚本语言生成图表和流程图。
  • Utils - 收集有用的 PHP 函数、迷你类和日常片段。
  • Image - 包提供了一种面向对象的简单方式来处理图像。
  • 数据 - ArrayObject的扩展实现。使用文件作为配置/数组。
  • Retry - 一个小巧的PHP库,提供重试/退避功能,支持多种退避策略和抖动支持。
  • SimpleTypes - 转换任何值和度量 - 货币、重量、汇率、长度等。