CLI 库

CodeIgniter 的 CLI 库使创建交互式命令行脚本变得简单,包括

  • 提示用户输入更多信息

  • 在终端中写入多色文本

  • 发出蜂鸣声(请友善!)

  • 在长时间任务期间显示进度条

  • 将长文本行换行以适应窗口。

初始化类

您不需要创建 CLI 库的实例,因为它的所有方法都是静态的。相反,您只需要确保您的控制器可以通过类上面的 use 语句找到它

<?php

namespace App\Commands;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;

class MyCommand extends BaseCommand
{
    // ...

    public function run(array $params)
    {
        // ...
    }
}

该类在文件首次加载时自动初始化。

从用户获取输入

有时您需要向用户索取更多信息。他们可能没有提供可选的命令行参数,或者脚本可能遇到了现有文件,需要在覆盖之前进行确认。这可以通过 prompt()promptByKey() 方法处理。

注意

从 v4.3.0 开始,您可以使用 PhpStreamWrapper 为这些方法编写测试。请参阅 测试 CLI 输入

prompt()

您可以通过将问题作为第一个参数传递来提供问题

<?php

use CodeIgniter\CLI\CLI;

$color = CLI::prompt('What is your favorite color?');

您可以提供一个默认答案,如果用户只按回车键,则将使用该答案,并将默认值作为第二个参数传递

<?php

use CodeIgniter\CLI\CLI;

$color = CLI::prompt('What is your favorite color?', 'blue');

您可以通过将允许的答案数组作为第二个参数传递来限制可接受的答案

<?php

use CodeIgniter\CLI\CLI;

$overwrite = CLI::prompt('File exists. Overwrite?', ['y', 'n']);

最后,您可以将 验证 规则作为第三个参数传递给答案输入

<?php

use CodeIgniter\CLI\CLI;

$email = CLI::prompt('What is your email?', null, 'required|valid_email');

验证规则也可以用数组语法编写

<?php

use CodeIgniter\CLI\CLI;

$email = CLI::prompt('What is your email?', null, ['required', 'valid_email']);

promptByKey()

提示的预定义答案(选项)有时需要描述,或者过于复杂,无法通过其值进行选择。 promptByKey() 允许用户通过其键而不是其值来选择选项

<?php

use CodeIgniter\CLI\CLI;

$fruit = CLI::promptByKey('These are your choices:', ['The red apple', 'The plump orange', 'The ripe banana']);
/*
 * These are your choices:
 *   [0]  The red apple
 *   [1]  The plump orange
 *   [2]  The ripe banana
 *
 * [0, 1, 2]:
 */

命名键也是可能的

<?php

use CodeIgniter\CLI\CLI;

$fruit = CLI::promptByKey(['These are your choices:', 'Which would you like?'], [
    'apple'  => 'The red apple',
    'orange' => 'The plump orange',
    'banana' => 'The ripe banana',
]);
/*
 * These are your choices:
 *   [apple]   The red apple
 *   [orange]  The plump orange
 *   [banana]  The ripe banana
 *
 * Which would you like? [apple, orange, banana]:
 */

最后,您可以将 验证 规则作为第三个参数传递给答案输入,可接受的答案会自动限制为传递的选项。

promptByMultipleKeys()

版本 4.3.0 中的新增功能。

此方法与 promptByKey() 相同,但它支持多个值。

<?php

use CodeIgniter\CLI\CLI;

$hobbies = CLI::promptByMultipleKeys('Select your hobbies:', ['Playing game', 'Sleep', 'Badminton']);
/*
 * Select your hobbies:
 *   [0]  Playing game
 *   [1]  Sleep
 *   [2]  Badminton
 *
 * You can specify multiple values separated by commas.
 * [0, 1, 2]:
 *
 * if your answer is '0,2', the return is the key and the value of the options :
 * [
 *   [0] => "Playing game",
 *   [2] => "Badminton"
 * ]
 */

重要

promptByKey() 不同,方法 promptByMultipleKeys() 不支持命名键或验证。

提供反馈

write()

提供了一些方法供您向用户提供反馈。这可以像简单的状态更新一样简单,也可以像复杂的信息表一样复杂,该信息表会包装到用户的终端窗口中。这的核心是 write() 方法,它将要输出的字符串作为第一个参数

<?php

use CodeIgniter\CLI\CLI;

CLI::write('The rain in Spain falls mainly on the plains.');

您可以通过将颜色名称作为第二个参数传递来更改文本的颜色

<?php

use CodeIgniter\CLI\CLI;

CLI::write('File created.', 'green');

这可以用来通过状态区分消息,或者通过使用不同的颜色创建“标题”。您甚至可以通过将颜色名称作为第三个参数传递来设置背景颜色

<?php

use CodeIgniter\CLI\CLI;

CLI::write('File overwritten.', 'light_red', 'dark_gray');

以下前景色可用

  • 黑色

  • 深灰色

  • 蓝色

  • 深蓝色

  • 浅蓝色

  • 绿色

  • 浅绿色

  • 青色

  • 浅青色

  • 红色

  • 浅红色

  • 紫色

  • 浅紫色

  • 浅黄色

  • 黄色

  • 浅灰色

  • 白色

还有一些颜色可作为背景色

  • 黑色

  • 蓝色

  • 绿色

  • 青色

  • 红色

  • 黄色

  • 浅灰色

  • 洋红色

print()

Print 函数与 write() 方法的功能相同,区别在于它不会在打印内容前后强制换行。它会将内容打印到当前光标所在的位置。这使您可以从不同的调用中打印多个项目,并将它们都放在同一行上。当您想要显示状态,执行某些操作,然后在同一行上打印“完成”时,这将非常有用。

<?php

use CodeIgniter\CLI\CLI;

for ($i = 0; $i <= 10; $i++) {
    CLI::print($i);
}

color()

虽然 write() 命令会将单行写入终端,并在末尾添加一个 EOL 字符,但您可以使用 color() 方法创建字符串片段,该片段可以以相同的方式使用,但它不会在打印后强制添加 EOL。这使您可以在同一行上创建多个输出。或者,更常见的是,您可以在 write() 方法中使用它来创建不同颜色的字符串。

<?php

use CodeIgniter\CLI\CLI;

CLI::write("fileA \t" . CLI::color('/path/to/file', 'white'), 'yellow');

此示例将向窗口写入单行,其中 fileA 为黄色,后面跟着一个制表符,然后是 /path/to/file,以白色文本显示。

error()

如果您需要输出错误,则应使用名为 error() 的方法。该方法会将浅红色文本写入 STDERR,而不是像 write()color() 那样写入 STDOUT。如果您有脚本在监视错误,这将非常有用,因为它们不必筛选所有信息,只需要实际的错误消息即可。您可以像使用 write() 方法一样使用它。

<?php

use CodeIgniter\CLI\CLI;

CLI::error('Cannot write to file: ' . $file);

wrap()

此命令将获取一个字符串,从当前行开始打印它,并将它换行到设定的长度。当您显示带有描述的选项列表时,这可能很有用,您希望将这些描述在当前窗口中换行,而不是超出屏幕。

<?php

use CodeIgniter\CLI\CLI;

CLI::color("task1\t", 'yellow');
CLI::wrap('Some long description goes here that might be longer than the current window.');

默认情况下,字符串将在终端宽度处换行。Windows 目前没有提供确定窗口大小的方法,因此我们默认使用 80 个字符。如果您想将宽度限制为更短的长度,以确保它适合窗口,请将最大行长作为第二个参数传递。这将在最近的单词边界处断开字符串,以避免单词被截断。

<?php

use CodeIgniter\CLI\CLI;

// Wrap the text at max 20 characters wide
CLI::wrap($description, 20);

您可能会发现,您希望在标题、文件或任务的左侧有一个列,而在右侧有一个包含其描述的文本列。默认情况下,这将换回到窗口的左边缘,这将不允许项目在列中对齐。在这种情况下,您可以传递一定数量的空格来填充第一行之后的每一行,这样您将在左侧有一个清晰的列边缘。

<?php

use CodeIgniter\CLI\CLI;

$titles = [
    'task1a',
    'task1abc',
];
$descriptions = [
    'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
    "Lorem Ipsum has been the industry's standard dummy text ever since the",
];

// Determine the maximum length of all titles
// to determine the width of the left column
$maxlen = max(array_map('strlen', $titles));

for ($i = 0; $i < count($titles); $i++) {
    CLI::write(
        // Display the title on the left of the row
        substr(
            $titles[$i] . str_repeat(' ', $maxlen + 3),
            0,
            $maxlen + 3
        ) .
        // Wrap the descriptions in a right-hand column
        // with its left side 3 characters wider than
        // the longest item on the left.
        CLI::wrap($descriptions[$i], 40, $maxlen + 3)
    );
}

将创建类似这样的内容

task1a     Lorem Ipsum is simply dummy
           text of the printing and
           typesetting industry.
task1abc   Lorem Ipsum has been the
           industry's standard dummy
           text ever since the

newLine()

The newLine() 方法向用户显示一个空行。它不接受任何参数。

<?php

use CodeIgniter\CLI\CLI;

CLI::newLine();

clearScreen()

您可以使用 clearScreen() 方法清除当前终端窗口。在大多数版本的 Windows 中,这将只插入 40 个空行,因为 Windows 不支持此功能。Windows 10 bash 集成应该改变这一点。

<?php

use CodeIgniter\CLI\CLI;

CLI::clearScreen();

showProgress()

如果您有一个长时间运行的任务,您希望让用户了解进度,您可以使用 showProgress() 方法,它将显示类似以下内容

[####......] 40% Complete

此块在原地进行动画处理,效果非常不错。

要使用它,请将当前步骤作为第一个参数传递,并将总步骤数作为第二个参数传递。完成百分比和显示长度将根据该数字确定。完成后,将 false 作为第一个参数传递,进度条将被移除。

<?php

use CodeIgniter\CLI\CLI;

$totalSteps = count($tasks);
$currStep   = 1;

foreach ($tasks as $task) {
    CLI::showProgress($currStep++, $totalSteps);
    $task->run();
}

// Done, so erase it...
CLI::showProgress(false);

table()

<?php

use CodeIgniter\CLI\CLI;

$thead = ['ID', 'Title', 'Updated At', 'Active'];
$tbody = [
    [7, 'A great item title', '2017-11-15 10:35:02', 1],
    [8, 'Another great item title', '2017-11-16 13:46:54', 0],
];

CLI::table($tbody, $thead);
+----+--------------------------+---------------------+--------+
| ID | Title                    | Updated At          | Active |
+----+--------------------------+---------------------+--------+
| 7  | A great item title       | 2017-11-16 10:35:02 | 1      |
| 8  | Another great item title | 2017-11-16 13:46:54 | 0      |
+----+--------------------------+---------------------+--------+

wait()

等待一定秒数,可以选择显示等待消息并等待按键。

<?php

use CodeIgniter\CLI\CLI;

// wait for specified interval, with countdown displayed
CLI::wait($seconds, true);

// show continuation message and wait for input
CLI::wait(0, false);

// wait for specified interval
CLI::wait($seconds, false);