PHP 并非广受关注的命令行脚本语言,但这很可惜,因为 PHP 拥有许多使其成为编写终端应用程序的理想选择的特性。
本系列文章将介绍如何使用 Macrame 库编写交互式命令行脚本。我们将逐步完成一个示例项目,该脚本从头到尾获取 Mastodon 用户关注者列表,并涵盖以下主题:获取和验证用户输入、构建交互式菜单、处理命令行参数、安全访问文件、设置输出文本样式以及在向用户显示动画加载器时在后台运行函数。
有关 Macrame 的更多信息,请访问文档站点。
我们将要完成的项目是一个简单的命令行脚本,用于返回 Mastodon 用户的关注者列表。运行该脚本如下所示:
用户从动态菜单中选择所需的 Mastodon 实例,输入用户名作为自由文本,脚本在获取数据时显示动画加载器。输出是一个漂亮的 ASCII 风格表格。
对于想要跳过此步骤的任何人,此项目的完整源代码都以 gist 的形式提供。
在本部分中,我们将介绍如何:
通过 Composer 安装 Macrame:
<code class="language-bash">composer require gbhorwood/macrame</code>
安装 Macrame 后,我们可以设置一个基本的“Hello World”脚本并将其用作我们的起始样板。虽然从技术上讲,此框架并非必需,但使用它会使我们的脚本更安全、更符合规范。让我们来看一下代码:
<code class="language-php">#!/usr/bin/env php <?php require __DIR__ . '/vendor/autoload.php'; use Gbhorwood\Macrame\Macrame; // 实例化 Macrame 对象。 // 参数是 ps(1) 所见的脚本名称 $macrame = new Macrame("示例 Macrame 脚本"); // 强制仅在命令行上执行脚本时才运行脚本 if ($macrame->running()) { // 验证主机系统是否可以运行 Macrame 脚本。失败时退出 $macrame->preflight(); // 将文本输出到 STDOUT $macrame->text("Hello World")->write(); // 清洁退出 $macrame->exit(); }</code>
虽然代码行不多,但这里发生了很多事情。让我们来仔细看看。
<code class="language-php">#!/usr/bin/env php</code>
这一行是“shebang”。基本上,它告诉我们的类 Linux 操作系统使用哪个解释器来运行此脚本。这允许我们运行脚本而无需先键入 php。shebang 必须是文件的第一行,甚至在
<code class="language-php">$macrame = new Macrame("示例 Macrame 脚本");</code>
在这里,我们创建了一个 Macrame 对象,我们将在脚本的其余部分使用它。非常标准的内容。唯一有趣的部分是参数。这是操作系统将赋予我们脚本的名称。例如,如果我们运行 ps 以显示正在运行的进程列表,我们的脚本将显示此名称。
if ($macrame->running())
此语句确保块内的所有代码仅在命令行上运行脚本时才执行。
<code class="language-bash">composer require gbhorwood/macrame</code>
登录后复制登录后复制登录后复制
当我们为命令行编写 PHP 时,我们对环境的控制不如我们拥有和管理的 Web 服务器那样多。此处的 preflight() 调用测试本地 PHP 环境,如果它不满足最低要求,则会终止脚本并显示错误消息。最低要求是:
- PHP 7.4
- posix 扩展
- mbstring 扩展
注意:虽然 Macrame 在 PHP 7.4 和 8.0 上运行,但由于 PHP 在 8.1 中处理多字节字符串的方式发生了变化,因此在 PHP 8.1 之前的版本中,包含表情符号的字符串在输出中可能无法正确对齐。
<code class="language-php">#!/usr/bin/env php
<?php require __DIR__ . '/vendor/autoload.php';
use Gbhorwood\Macrame\Macrame;
// 实例化 Macrame 对象。
// 参数是 ps(1) 所见的脚本名称
$macrame = new Macrame("示例 Macrame 脚本");
// 强制仅在命令行上执行脚本时才运行脚本
if ($macrame->running()) {
// 验证主机系统是否可以运行 Macrame 脚本。失败时退出
$macrame->preflight();
// 将文本输出到 STDOUT
$macrame->text("Hello World")->write();
// 清洁退出
$macrame->exit();
}</code>
登录后复制登录后复制登录后复制登录后复制
这会干净地退出脚本,返回 0 的成功代码。此外,执行期间创建的任何临时文件都将自动删除。最好使用 Macrame 的 exit() 函数而不是 PHP 的 die();
运行 Hello World
编写完基本的“Hello World”脚本后,我们可以设置其权限以允许执行并在命令行上运行它。
<code class="language-php">#!/usr/bin/env php</code>
登录后复制登录后复制登录后复制登录后复制
读取参数
Macrame 提供了一套用于解析和读取命令行参数的工具。让我们从一些简单的事情开始:在使用以下命令调用脚本时获取版本号:
<code class="language-php">$macrame = new Macrame("示例 Macrame 脚本");</code>
登录后复制登录后复制登录后复制登录后复制
对于这种情况,我们只需要检查这些参数是否存在即可。
我们可以通过调用 Macrame 对象上的 args() 方法来实现此目的,该方法返回一个包含所有脚本参数和我们可以用来检查它们的众多方法的对象。要测试参数是否存在,我们可以使用 exists() 方法,如下所示:
<code class="language-php">if ($macrame->running())</code>
登录后复制登录后复制
exists() 方法返回布尔值。
? Macrame 调用旨在进行链式调用。
命令行参数也可用于为变量赋值。例如,要设置用户名值,我们可能希望用户能够像这样调用脚本:
<code class="language-php">$macrame->preflight();</code>
登录后复制登录后复制
要在我们的脚本中获取此参数的值,我们可以使用 args() 提供的 first() 方法,如下所示:
<code class="language-php">$macrame->exit();</code>
登录后复制登录后复制
顾名思义,first() 方法返回参数的第一个出现的值。如果我们像这样调用脚本:
<code class="language-bash">chmod 755 ./examplescript.php
./examplescript.php</code>
登录后复制
那么 first() 将返回“firstuser”值。如果我们想要最后一个值,我们可以调用 last()。如果我们想要所有值作为数组,我们将使用 all()。
将所有这些放在一起,我们的脚本现在看起来像这样:
<code class="language-bash">./examplescript.php --version
# 或
./examplescript.php -v</code>
登录后复制
处理命令行参数的完整方法列表在 Macrame 参数文档中有所介绍。
创建动态菜单
我们还希望允许用户以交互方式使用我们的脚本。如果他们没有在命令行上传递参数,我们将提示他们输入数据。对于 Mastodon 实例值,我们将使用菜单。
Macrame 菜单是动态的;用户可以使用箭头键上下移动列表,然后按 键进行选择。
让我们编写一个向用户显示菜单并返回所选值的函数:
<code class="language-bash">composer require gbhorwood/macrame</code>
登录后复制登录后复制登录后复制
此处的核心功能是对以下内容的调用:
<code class="language-php">#!/usr/bin/env php
<?php require __DIR__ . '/vendor/autoload.php';
use Gbhorwood\Macrame\Macrame;
// 实例化 Macrame 对象。
// 参数是 ps(1) 所见的脚本名称
$macrame = new Macrame("示例 Macrame 脚本");
// 强制仅在命令行上执行脚本时才运行脚本
if ($macrame->running()) {
// 验证主机系统是否可以运行 Macrame 脚本。失败时退出
$macrame->preflight();
// 将文本输出到 STDOUT
$macrame->text("Hello World")->write();
// 清洁退出
$macrame->exit();
}</code>
登录后复制登录后复制登录后复制登录后复制
我们提供一个字符串数组作为菜单选项,以及一个可选的菜单标题文本,用于 menu()->interactive(),菜单会自动显示给用户。用户的选择将作为字符串返回。
通过向我们的链中添加对 erase() 的调用,还可以选择在用户做出选择后从屏幕上擦除菜单。此方法是可选的,但确实可以保持整洁。
获得菜单函数后,我们可以修改获取 Mastodon 实例的方式。我们将尝试从命令行参数中读取它,如果未传递任何值,则调用我们的 menuInstance() 函数。
<code class="language-php">#!/usr/bin/env php</code>
登录后复制登录后复制登录后复制登录后复制
关于菜单样式的补充说明
默认情况下,Macrame 使用终端的默认样式和颜色来显示菜单,并将突出显示的项目设置为反向显示。如果需要,我们可以通过向我们的链中添加一些额外的函数来更改此设置。例如,如果我们更希望突出显示的项目显示为粗体红色文本,我们可以这样写:
<code class="language-php">$macrame = new Macrame("示例 Macrame 脚本");</code>
登录后复制登录后复制登录后复制登录后复制
菜单文档页面上完整概述了可用于自定义菜单的颜色、样式和对齐方式的所有方法。
读取一行用户输入
接下来,我们将修改获取用户名的方式,使其也接受交互式输入。在这种情况下,我们将使用 input()->readline() 读取用户输入文本字符串。以下是该函数:
<code class="language-php">if ($macrame->running())</code>
登录后复制登录后复制
此函数的最后一行是我们轮询用户输入的地方。readline() 方法接受可选的 $prompt 参数;我们显示给用户的文本告诉他们应该输入什么。返回值是用户输入的字符串。
关于输入验证的补充说明
用户会犯错。这就是为什么输入验证很重要。
Macrame 附带了许多预设方法来验证输入。我们可以将任意数量的验证器添加到我们的链中,如果任何验证器失败,系统将提示用户再次输入。input()->readline() 函数只有在所有验证器都通过后才会返回值。
让我们来看一个例子:
<code class="language-php">$macrame->preflight();</code>
登录后复制登录后复制
在这里,我们应用了两个验证测试:文本必须为四个或更多个字符,并且不能包含“@”符号。对于这两种验证方法,第二个参数是如果验证失败我们将向用户显示的错误消息。
Macrame 输入文档页面上提供了所有预构建验证函数的完整列表。如果我们想编写自己的自定义验证器,那也在其中有所介绍。
那么“点状回显”输出呢?
如果我们的用户输入的是敏感数据,例如密码,我们可能不希望将他们的按键回显到终端,以免被窥探者看到。
为了解决这个问题,Macrame 提供了 readline() 的“点状回显”版本,称为 readPassword()。
<code class="language-php">$macrame->exit();</code>
登录后复制登录后复制
readPassword() 读取的每个按键都会以星号的形式回显。
设置文本样式
在如何读取一行用户文本的示例中,我们看到了大量用于设置提示文本样式的代码。让我们更详细地研究一下。
Macrame 允许使用 ANSI 代码设置终端文本输出样式,这使我们可以将粗体和斜体等样式以及颜色应用于我们的文本。
我们可以通过两种方式之一在我们的脚本中执行此操作。有一些方法,例如 style() 和 colour()(或 color()),或者我们可以使用基本的文本标记系统。
让我们首先看看方法方法。
<code class="language-bash">composer require gbhorwood/macrame</code>
登录后复制登录后复制登录后复制
在这里,我们使用 Macrame 的 text() 方法创建了一个“text”对象,然后应用样式和颜色,最后使用 get() 将其作为字符串返回。
请注意,样式和颜色方法应用于字符串中的所有文本。如果我们想要将样式化和着色的文本与纯文本混合,我们将不得不创建许多子字符串并将它们连接在一起。这可能会很麻烦,尤其是在处理大量文本时。
或者,我们可以使用 Macrame 的标记系统来简化文本样式设置。这是一个示例:
<code class="language-php">#!/usr/bin/env php
<?php require __DIR__ . '/vendor/autoload.php';
use Gbhorwood\Macrame\Macrame;
// 实例化 Macrame 对象。
// 参数是 ps(1) 所见的脚本名称
$macrame = new Macrame("示例 Macrame 脚本");
// 强制仅在命令行上执行脚本时才运行脚本
if ($macrame->running()) {
// 验证主机系统是否可以运行 Macrame 脚本。失败时退出
$macrame->preflight();
// 将文本输出到 STDOUT
$macrame->text("Hello World")->write();
// 清洁退出
$macrame->exit();
}</code>
登录后复制登录后复制登录后复制登录后复制
在 和 标记之间的文本将被加粗(当然)。文档中列出了所有标记的完整列表。
需要注意的一点是,标记会关闭所有之前的标记。这是由于 ANSI 转义码的行为所致。
这意味着嵌套标记不会像我们预期的那样工作。例如,在此示例中,第一个标记会关闭 和 标记:
<code class="language-php">#!/usr/bin/env php</code>
登录后复制登录后复制登录后复制登录后复制
目前的脚本
到目前为止,我们的示例脚本如下所示:
<code class="language-php">$macrame = new Macrame("示例 Macrame 脚本");</code>
登录后复制登录后复制登录后复制登录后复制
接下来是什么
到目前为止,我们已经介绍了读取命令行参数、从菜单和文本中获取用户输入以及对输出进行一些基本的文本样式设置。在下一篇文章中,我们将介绍:
- 在向用户显示动画加载器时在后台运行函数
- 安全地写入文件
- 将数组数据作为格式良好的 ASCII 表格输出
- 分页显示长输出
- 基本的通知级别输出
? 本文最初发表在 Grant Horwood 技术博客中
以上是PHP:使用MACRAME编写命令行应用程序。 Pt 1的详细内容。更多信息请关注PHP中文网其他相关文章!