从零开始构建 PHP 命令行微框架四:minicli 功能详解
在之前构建 Minicli 的章节中,我们演示了使用 PHP 为 只有 CLI 的应用程序引导无依赖项微框架的步骤。
Minicli 是作为一个教育实验创建的,也是一个轻量级的基础,让我可以在我的个人项目中重复使用。我喜欢把它看作我能组装起来的最基本的单元,在它的基础上我可以建造我的玩具。
自从我分享我关于这个系列的最新帖子以来,已经有几个月了,我不愿分享我一直在做的工作,因为它总是感觉像是一件不完整的工作。但是它会不会是完整的(或者感觉是这样的)呢? 大概不会吧。Minicli 从一开始就是开源的,虽然我从来没有打算把它变成一个主流项目,但我也认为它可以帮助那些对在命令行中构建简单事物感兴趣的人,而不会被几十个外部要求所阻碍。
因此,我想正式向你介绍 Minicli,这是一个高度实验性的、无依赖关系的、以 cli 为中心的 PHP 应用程序微框架。
虽然我不主张重新发明应用程序中的所有轮子,但我认为应该有一个起点,不需要10多个不同的库来进行基本的命令解析和路由。从那里开始,就外部库而言,你应该能够有意识地选择你将依赖什么。 Minicli 是我为了解决这种情况而想出来的。
到目前为止,我和 Minicli一起构建的东西:
Dolphin,用于从命令行管理DigitalOcean droplets 的命令行工具。
我的网站,一种静态内容CMS,摘自我的 DEV 帖子。我将这作为一个单独的项目开源,名为 Librarian (Wip)。
在这篇文章中,你将学习如何使用 Minicli 在 PHP 中创建一个简单的 CLI 应用程序。
创建项目
你需要php-cli
命令和 Composer 才能开始。
使用以下命令创建新项目:
composer create-project --prefer-dist minicli/application myapp
安装完成后,你可以使用以下命令运行minicli
命令:
cd myapp
./minicli
这将向你显示默认的应用程序签名。
Minicli 附带的help
命令在app/Command/help/DefaultController.php
中定义,可自动生成可用命令树:
./minicli help
Available Commands
help
└──test
定义在app/Command/Help/TestController.php
中的help test
命令显示了参数的输出测试:
./minicli help test user=erika name=value
Hello, erika!
Array
(
[user] => erika
[name] => value
)
创建你的第一个命令
创建命令最简单的方式是编辑minicli
命令脚本,通过registerCommand
在应用程序内定义一个新命令为匿名函数:
#!/usr/bin/php
<?php
if (php_sapi_name() !== 'cli') {
exit;
}
require __DIR__ . '/vendor/autoload.php';
use Minicli\App;
use Minicli\Command\CommandCall;
$app = new App();
$app->setSignature('./minicli mycommand');
$app->registerCommand('mycommand', function(CommandCall $input) {
echo "My Command!";
var_dump($input);
});
$app->runCommand($argv);
然后,你可以使用以下命令执行新命令:
./minicli mycommand
Using Command Controllers
要将命令组织到控制器中,你需要使用 命令命名空间.
假设你想创建一个名为hello
的命令。你应该先在app/Commands
目录下新建一个目录:
mkdir app/Commands/Hello
现在,Hello
是你的命令命名空间。在该目录中,你需要至少创建一个命令控制器。可以从DefaultController
开始,当不提供子命令时,默认调用该DefaultController
。
这个名为DefaultController
的类可能是这样的:
<?php
namespace App\Command\Hello;
use Minicli\Command\CommandController;
class DefaultController extends CommandController
{
public function handle()
{
$this->getPrinter()->display("Hello World!");
}
}
此命令可通过以下方式使用:
./minicli hello
由于没有提供子命令,因此推断你要执行DEFAULT命令。 也可以通过以下方式调用此命令:
./minicli hello default
放置在Hello
命名空间中的任何其他命令控制器都将以类似的方式使用。例如,假设你想要创建一个新的子命令,如hello capps
。
然后,你创建一个名为CapsController
的新命令控制器:
<?php
namespace App\Command\Hello;
use Minicli\Command\CommandController;
class CapsController extends CommandController
{
public function handle()
{
$this->getPrinter()->display("HELLO WORLD!");
}
}
此新命令将以以下方式提供:
./minicli hello caps
使用参数
Minicli 对命令调用参数使用了一些约定:
- Args / Arguments: 解析的参数 - 任何来自 $argv 都不是
key=value
,也不是--flag
的内容。 - Params / Parameters: 键值对,如:
user=erika
- Flags: 单个参数前缀为
--
,如--update
父类CommandController
提供了几个使用命令调用参数的方便方法。
例如,假设你想要更新前面的hello
命令,以使用一个可选参数告诉将要问候的人的姓名。
<?php
namespace App\Command\Hello;
use Minicli\Command\CommandController;
use Minicli\Input;
class HelloController extends CommandController
{
public function handle()
{
$name = $this->hasParam('user') ? $this->getParam('user') : 'World';
$this->getPrinter()->display(sprintf("Hello, %s!", $name));
}
}
现在,要使用该命令的自定义版本,你需要运行:
./minicli hello user=erika
你将获得以下输出:
Hello, erika!
CommandCall
类方法
hasParam(string $key) : bool
- 如果参数存在,则返回 TRUE。getParam(string $key) : string
- 返回参数,如果参数不存在,则返回 NULL。hasFlag(string $key) : bool
- 返回是否在命令调用中传递了标志。
打印输出
CliPrinter
类提供了打印各种颜色和样式的消息的快捷方法。
它附带两个捆绑的主题:regular
和 unicorn
。这是在应用引导配置数组中设置的,默认设置为使用regular
主题。
public function handle()
{
$this->getPrinter()->info("Starting Minicli...");
if (!$this->hasParam('message')) {
$this->getPrinter()->error("Error: you must provide a message.");
exit;
}
$this->getPrinter()->success($this->getParam('message'));
}
CliPrinter
类方法
display(string $message) : void
- 显示以新行换行的消息。error(string $message) : void
- 使用当前主题颜色在新行中显示错误消息。success(string $message) : void
- 使用当前主题颜色在新行中显示成功消息。info(string $message) : void
- 使用当前主题颜色在新行中显示信息消息。newline() : void
- 打印新行。format(string $message, string $style="default") : string
- 返回具有所需样式的格式化字符串。out(string $message) : void
- 打印一条消息。
结束
Minicli 是一项正在进行中的工作,但你已经可以将其用作极简主义基础,在此基础上你可以构建有趣的玩具项目或有用的命令行工具,如Dolphin。
以下是我想用 Minicli 构建的一些想法,但到目前为止还没有时间(如果有人构建这些想法,我绝对不会介意):
- 基于文本的RPG游戏
- 推特机器人
- 找到你的推特互助工具
- 一款基于CLI的测验游戏
如果你想尝试一下 Minicli,请查看documentation网站了解更多详细信息,如果你有任何问题,请不要犹豫留下评论:)
*CliPrinter
类提供了打印各种颜色和样式的消息的快捷方法。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。