ruigweb/commander

您CLI命令的神奇指挥官。

安装: 0

依赖: 0

建议者: 0

安全: 0

星星: 0

关注者: 1

分支: 0

开放问题: 2

类型:项目

dev-main 2023-06-22 09:05 UTC

This package is auto-updated.

Last update: 2024-09-18 21:50:39 UTC


README

Test Coverage Tests Packagist Downloads (custom server) Packagist Version (custom server)

🫡 指挥!

command('Make it awesome', null, function() {
    return 'Anytime!';
});

掌控命令行,并指导它运行任何命令。Commander提供了一种独立于框架的方式,为您的PHP应用程序创建CLI命令。简单,如您所愿。当您的某个命令被执行时会发生什么?您能想到的任何事情!您的应用程序,您的CLI命令。

Commander可在Packagist上找到,建议通过运行以下命令通过composer安装Commander

$ php composer require ruigweb/commander

现在在您的应用程序根目录中创建一个空的commander.php文件。

那么,一切都已经安装好了?让我们从简单开始

# ./commander.php

return [
    command('March', null, fn() => echo 'Marching'),
    command('Halt', null, fn() => echo 'At Ease')
];

当然,我们现在有两个命令,那么我们如何使用它们?🤔

$ php vendor/bin/instruct March
$ Marching

很简单,只需使用Commander提供的vendor/bin/instruct来执行您的命令。

假设您的自己的命令会更复杂一些 😏,我们将进一步探讨。

return [
    command('March', argv(
        argument('direction'),
    ), fn() => echo 'Marching'),
    command('Halt', argv(
        option('in', 'int', '0'),
    ), fn() => echo 'At Ease')
];

我们现在为我们的命令提供一些参数,这些参数可以在执行命令时提供。这些参数可以是位置参数可选参数。除了参数的名称外,您还可以定义提供的值应该如何解析,以及其默认值。参数当前可以解析为字符串(默认)、整数和布尔值。

很好,这些都是好的,但是如何使用这些参数呢?

$ php vendor/bin/instruct March forward
$ Marching

$ php vendor/bin/instruct Halt --in=5
$ At Ease

所以我们提供了参数,但我们并没有真正使用它们...这就是处理程序发挥作用的地方。处理程序是在命令执行时将执行的回调。Commander基本上通过您定义的处理程序在CLI和您的应用程序之间提供了一个层。接下来,在我们的示例中,我们将创建一些处理程序来处理输入。最简单的处理程序形式是基本的闭包。在后台,它将使用Closure::fromCallable功能来执行您的处理程序。

return [
    command('March', argv(
        argument('direction'),
    ), function($argv) {
        return 'Marching '.$argv['direction'];
    }),
    command('Halt', argv(
        option('in', 'int', '0'),
    ), function($argv) {
        return 'At Ease in '. (string) $argv['in'].' minutes';
    });
];
$ php vendor/bin/instruct March forward
$ Marching forward

$ php vendor/bin/instruct Halt --in=5
$ At Ease in 5 minutes

所以这些都是基础知识,但是发挥一些想象力,可能性是无穷的。您是魔术师,让它变得精彩!

深入了解

以下部分将更详细地描述Commander的构建块。

协调器

协调器充当容器,您的命令在其中注册。有几种方法可以在协调器上注册您的命令。一旦您尝试使用vendor/bin/instruct使用vendor/bin/instruct执行某个命令,协调器将尝试以下步骤来定位并执行您的命令。

COMMANDER_REGISTER

它将验证是否存在可选的COMMANDER_REGISTER环境变量。如果此变量存在,它将尝试要求一个文件并使用响应来注册您的命令。

commander.php

下一步将是尝试在项目根目录中定位一个commander.php文件。项目的根目录被定义为包含composer vendor目录的目录。此root可以由APP_PATH环境变量定义。如果存在commander.php文件,它将注册您的命令。

COMMANDER_COORDINATOR

当前两个失败时,最后一个步骤是创建/加载协调器。如果存在COMMANDER_COORDINATOR环境变量,它将使用该变量构建协调器,否则将构建一个新的协调器。此最后一步可用于更复杂的协调器使用方式,例如在执行instruct之前注册自定义协调器。

自定义

如果以上步骤都不能提供一种在您的应用程序中使用Commander的合理方法,您也可以自己开始使用Coordinator。只需在您期望的位置构造一个新的Coordinator,并按您的意愿注册命令。

$coordinator = new Coordinator;
$coordinator->register(new Command('March'));

Coordinator允许通过创建多个Coordinator来在不同部分分离命令。

$coordinator = new Coordinator('A');
$coordinator->register(new Command('Register to Coordinator A'));

$coordinator = new Coordinator('B');
$coordinator->register(new Command('Register to Coordinator B'));

可以通过当前上下文流将命令注册到Coordinator中。Coordinator存储在Coordinator类本身的静态属性中,因此每次PHP脚本执行时都会进行重置。

命令

use Ruigweb\Commander\Command;

$command = new Command('name', new Argv, function(Argv $argv) {}, 'description');

// Helper
$command = command('name', new Argv, function(Argv $argv) {}, 'description');

基本上,Command是一种定义Commander如何处理用户输入的方法。允许用户根据已注册的命令执行处理程序。一个Command只有一个必需的参数,即其名称。但是,值得注意的是,如果没有定义处理程序,则无法执行命令。可选的描述将用于在Command--help上提供额外的帮助信息。

处理程序是通过使用Closure::fromCallable函数执行的。提供给处理程序的参数是一个包含用户输入解析并通过此实例提供的Argv实例。

(位置/可选)参数

对于每个命令,都可以定义在执行命令时可以提供哪些位置和可选参数。显然,按照它们应该提供的顺序提供位置参数很重要。对于每个参数,您都可以提供名称、类型和默认值。类型将定义提供的参数值应该如何解析。当提供了默认值时,它将在该参数未被提供时使用。

$argument = new Argument('positional', 'int', 0);

$optional = new Option('optional', 'string', 'Awesome');

可以通过在名称前加上--来提供可选参数。对于布尔类型可选参数,它还会自动创建一个缩写变体,可以使用。

$command = new Command('be', new Argv(
    new Option('awesome', 'bool', true)
));

// Register the command to a Coordinator
$ vendor/bin/instruct be --awesome
// or
$ vendor/bin/instruct be -a

您可以通过使用short方法来防止在命令中使用缩写。

$command = new Command('be', new Argv(
    (new Option('awesome', 'bool', true))->short(false)
));

Argv

Argv类用于定义和提供可以为命令使用的(可选)参数。这个类在初始化后是不可变的。它将用于解析为命令提供的输入,并将其提供给命令的处理程序。定义位置参数的顺序很重要。要读取执行命令时提供的已解析值,提供的Argv实例中的(位置)参数将为每个参数包含一个(默认)值。

$command = new Command('be', new Argv(
    (new Option('awesome', 'bool', true))
), function(Argv $argv) {
    return 'You are '.$argv['awesome'] === true ? 'awesome' : 'a bit boring';
});

当用户提供了不存在的可选参数或过多的位置参数时,Commander不会/错误地解析这些参数。当前实现不提供有关错误使用/提供的参数的任何反馈。

子命令

有时,将CLI命令结构化为使用子命令非常合适。例如,有不同命令来管理用户模型。

$ vendor/bin/instruct user create user51212@internet.com
$ vendor/bin/instruct user update user51212@internet.com user51212_udpated@internet.com

在上面的两个示例中,我们首先调用一个命令创建用户,然后调用另一个命令更新用户。为了简单起见,我们在这里管理的用户数据只有电子邮件地址。

要在Coordinator上创建和注册这样的子命令,您只需要为提供的Argv实例提供(子)命令作为第一个参数。什么?🤔

$userCommands = new Command('user', new Argv(
    new Command('create', 
        new Argv(
            new Argument('email')
        ),
        function(Argv $argv) {
            // Create a new user based on provided email address
        }
    ),
    new Command('update', 
        new Argv(
            new Argument('email'),
            new Argument('new_email')
        ),
        function(Argv $argv) {
            // Update a existing user based on provided email and new email address
        }
    ),
));

子命令可以递归创建,天高任鸟飞 ✨

单个命令

等等,我们已经讨论了命令的工作方式了,对吧?是的,但如果您的应用程序只有一个CLI命令怎么办?在这种情况下,您只需将您的Command(或任何可调用的)作为可解析的提供给您的Coordinator

$coordinator = (new Coordinator)->resolve(
    function(Argv $argv) {
        echo 'This is awesome!';
    }, 
    new Argv(
        new Option('reboot', 'bool')
    )
);

现在这个单个Command可以这样使用

$ vendor/bin/instruct --reboot

只是要注意,这是一个或另一个,或者一个命令/解析器来运行或注册命令 🤷‍♂️

辅助工具

为了让您的使用更加便捷,提供了一些辅助器来快速创建命令,例如。所有可用的辅助器都是对应类的简单快捷键。以下是一些可用的辅助器:coordinatorcommandargumentoption