用于简化使用PHP创建基于命令行应用程序的类库。

v1.3.0 2024-08-20 21:10 UTC

This package is auto-updated.

Last update: 2024-09-20 21:17:12 UTC


README

一个类库,可以帮助使用PHP编写具有最小依赖的基于命令行的应用程序。

内容

支持的PHP版本

功能

  • 帮助创建基于命令行的应用程序。
  • 支持交互式模式。
  • 支持ANSI输出。
  • 支持实现自定义输入和输出流。
  • 能够为命令编写测试并使用测试自动化工具测试它们。

示例应用程序

示例应用程序可以在以下位置找到: https://github.com/WebFiori/cli/tree/main/example

安装

要安装库,只需将其包含在composer.jsonrequire部分: "webfiori\cli":"*"

创建和运行命令

创建命令

创建新命令的第一步是创建一个扩展webfiori\cli\CLICommand类的新的类。该类CLICommand是一个实用类,它具有可以用来读取输入、发送输出和使用命令行参数的方法。

该类有一个必须实现的方法。该方法的主体中的代码将代表命令的逻辑。

<?php
//File 'src/SampleCommand.php'
use webfiori\cli\CLICommand;

class SampleCommand extends CLICommand {

    public function __construct(){
        parent::__construct('say-hi');
    }

    public function exec(): int {
        $this->println("Hi People!");
    }

}

运行命令

webfiori\cli\Runner类是用于管理执行命令逻辑的类。为了运行命令,必须创建该类的实例并使用它来注册命令并开始运行应用程序。

要注册命令,使用Runner::register()方法。要启动应用程序,使用Runner::start()方法。

// File src/main.php
require_once '../vendor/autoload.php';

use webfiori\cli\Runner;
use SampleCommand;


$runner = new Runner();
$runner->register(new SampleCommand());
exit($runner->start());

现在,如果打开终端并执行以下命令

php main.php say-hi

输出将是字符串Hi People!

参数

参数是从终端传递到PHP进程值的方式。它们可以用来配置命令的执行。例如,一个命令可能需要某种类型的文件作为输入。

向命令添加参数

参数可以按照以下方式添加到类的构造函数中

<?php
//File 'src/SampleCommand.php'
use webfiori\cli\CLICommand;
use webfiori\cli\Option;

class SampleCommand extends CLICommand {

    public function __construct(){
        parent::__construct('say-hi', [
            '--person-name' => [
                Option::OPTIONAL => true
            ]
        ]);
    }

    public function exec(): int {
        $this->println("Hi People!");
    }

}

参数可以作为关联数组或webfiori\cli\Argument类型对象的数组提供。在关联数组的情况下,索引是参数的名称,索引的值是子关联数组选项。每个参数都可以有以下选项

  • optional:一个布尔值。如果设置为true,则表示该参数是可选的。默认为false。
  • default:参数的默认值,如果未提供则使用。
  • description:参数的描述,当执行命令help时将显示。
  • values:参数可以具有的值集。如果提供,则只允许列表上的值。

可以使用webfiori\cli\Option类来访问选项。

访问参数值

通过使用方法 CLICommand::getArgValue(string $argName) 来访问参数的值。如果提供了参数,该方法将返回其值作为 string。如果没有提供,则返回 null

<?php
//File 'src/SampleCommand.php'
use webfiori\cli\CLICommand;
use webfiori\cli\Option;

class SampleCommand extends CLICommand {

    public function __construct(){
        parent::__construct('say-hi', [
            '--person-name' => [
                Option::OPTIONAL => true
            ]
        ]);
    }

    public function exec(): int {
        $personName = $this->getArgValue('--person-name');
        
        if ($personName !== null) {
            $this->println("Hi %s!", $personName);
        } else {
            $this->println("Hi People!");
        }
        
    }

}

交互式模式

交互模式是一种可以在同一PHP进程中保持应用程序运行并执行多个命令的方法。要启动应用程序的交互模式,在启动应用程序时添加参数 -i,如下所示

php main.php -i

这将在终端显示以下输出

>> Running in interactive mode.
>> Type command name or 'exit' to close.
>>

帮助 命令

库中默认提供的命令之一是 帮助 命令。它可以用来显示所有已注册命令的帮助说明。

注意:为了使用此命令,必须使用方法 Runner::register() 进行注册。

设置帮助说明

帮助说明由创建命令的开发者在实现期间提供。说明可以作为描述设置在扩展了类 webfiori\cli\CLICommand 的类的构造函数中。描述可以针对命令及其参数设置。

<?php
//File 'src/SampleCommand.php'
use webfiori\cli\CLICommand;
use webfiori\cli\Option;

class GreetingsCommand extends CLICommand {

    public function __construct() {
        parent::__construct('hello', [
            '--person-name' => [
                Option::DESCRIPTION => 'Name of someone to greet.',
                Option::OPTIONAL => true
            ]
        ], 'A command to show greetings.');
    }

    public function exec(): int {
        $name = $this->getArgValue('--person-name');

        if ($name === null) {
            $this->println("Hello World!");
        } else {
            $this->println("Hello %s!", $name);
        }

        return 0;
    }
}

运行help命令

帮助命令可以通过两种方式使用,一种是为应用程序显示一般帮助,另一种是为特定命令显示。

通用帮助

要显示应用程序的一般帮助,可以执行以下命令。

//File 'src/main.php'
php main.php help 

此命令的输出将如下所示

Usage:
    command [arg1 arg2="val" arg3...]

Global Arguments:
    --ansi:[Optional] Force the use of ANSI output.
Available Commands:
    help:          Display CLI Help. To display help for specific command, use the argument "--command-name" with this command.
    hello:         A command to show greetings.
    open-file:     Reads a text file and display its content.

注意:根据已注册的命令,输出可能不同。

特定命令的帮助

要显示特定命令的帮助说明,可以使用参数 --command-name 包含命令的名称,如下所示

//File 'src/main.php'
php main.php help --command-name=hello

此命令的输出将如下所示

hello:         A command to show greetings.
    Supported Arguments:
                --person-name:[Optional] Name of someone to greet.

单元测试命令

库提供了辅助类 webfiori\cli\CommandTestCase,可以用来为不同命令编写单元测试。开发者只需扩展该类并使用实用方法编写测试。该类基于 PHPUnit。

该类有两个可用于执行测试的方法

  • CommandTestCase::executeSingleCommand():用于一次运行一个命令并返回其输出。
  • CommandTestCase::executeMultiCommand():用于注册多个命令,设置默认命令和/或运行已注册的其中一个命令。

第一个方法适用于验证一个特定命令的输出。第二个方法对于模拟具有多个命令的应用程序的执行非常有用。

两种方法都支持模拟参数向量和用户输入。

namespace tests\cli;

use webfiori\cli\CommandTestCase;

class HelloCommandTest extends CommandTestCase {
    /**
     * @test
     */
    public function test00() {
        
        //Verify test results
        
        $this->assertEquals([
            "Hello World!\n"
        ], $this->executeSingleCommand(new HelloWorldCommand()));
        $this->assertEquals(0, $this->getExitCode());
    }
}

测试示例可以在这里找到