CI4原生支持CLI命令,需在app/Commands/下创建继承BaseCommand的类,定义$name和$description,实现run()方法,通过$this->params获取参数,用CLI::write()输出。

CodeIgniter 3 和 CodeIgniter 4 实现 CLI 命令的方式完全不同:CI3 必须靠“伪装 HTTP 环境 + 手动补全 $_SERVER 变量”才能跑通,而 CI4 原生支持、开箱即用,且提供 CLI 类封装交互逻辑。直接拿 CI3 的写法套到 CI4 上会报错,反之亦然。
CI4 中怎么注册一个可执行的 CLI 命令
CI4 把 CLI 命令视为独立于控制器的类,放在 app/Commands/ 目录下,继承 CodeIgniter\CLI\BaseCommand,并实现 run() 方法。
- 命令类必须有
$name属性(如'tools:hello'),冒号前是组名,后是命令名,终端里就用php spark tools:hello -
$description是必填项,否则php spark list不显示该命令 - 参数通过
$this->params获取(不是$argv),例如执行php spark tools:hello --name=John,则$this->params['name']为'John' - 不推荐在
run()里直接 echo 输出,应使用CLI::write(),它自动处理颜色、换行和 Windows 兼容性
CI3 中为什么不能直接运行 php index.php controller method
因为 CI3 的 index.php 在初始化时硬依赖 $_SERVER['REQUEST_METHOD']、$_SERVER['PATH_INFO'] 等 Web 环境变量,而 CLI 下它们根本不存在,导致 Undefined index: REQUEST_METHOD 或白屏。
- 必须另建入口文件(如
cli.php),手动预设关键变量:$_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['PATH_INFO'] = ''; - 需显式定义
ENVIRONMENT,否则日志可能写入错误目录 - CI3 的
$this->input->argv()只返回从第 3 个元素开始的参数(即跳过php和index.php),但原生$argv是完整的,别混用 - 不要在 CI3 CLI 控制器里调用
$this->input->get()或$this->input->post(),它们永远为空
如何让 CLI 命令只允许命令行访问,禁止 URL 调用
CI3 和 CI4 都提供了可靠的运行环境判断方式,但实现位置和推荐做法不同。
- CI3 推荐在控制器构造函数中加:
if (!$this->input->is_cli_request()) { show_error('CLI only.'); }—— 注意这个方法内部实际检查的是PHP_SAPI === 'cli' - CI4 更推荐在命令类的
run()开头加:if (is_cli() === false) { throw new \RuntimeException('This command must be run from the CLI.'); },因为命令类本身就不走控制器生命周期 - CI3 中还常见手动判断:
if (php_sapi_name() !== 'cli') { exit('No direct script access allowed'); },这个更底层、更可靠,但要放在入口或控制器最顶部
CLI 下读取用户输入和输出格式化容易踩哪些坑
CI4 的 CLI 类封装了交互能力,但默认行为和开发者直觉有偏差。
-
CLI::prompt()默认不回显用户输入(比如密码场景需要隐藏),若要明文输入,得加第四个参数:CLI::prompt('Password:', null, 'required', false) - 彩色输出要用
CLI::color('text', 'red'),直接写\033[31mtext\033[0m在 Windows CMD 下大概率失效 -
CLI::error()和CLI::success()自动加换行,重复调用CLI::write()会导致空行过多 - 长文本自动换行由
CLI::wrap()处理,但它的宽度默认按 80 字符算,如果终端更宽,得传入CLI::wrap($text, 120)
真正麻烦的从来不是写一个能跑的 CLI 命令,而是确保它在不同 PHP SAPI(cli/phpdbg)、不同操作系统(Linux/macOS/Windows)、不同终端宽度下行为一致——尤其是参数解析和用户输入反馈。CI4 的 spark 命令层已经做了大量适配,CI3 则几乎全靠自己兜底。


















