Skip to content

CLI 选项

概述

PHP CLI(命令行界面)提供了丰富的运行选项,用于控制 PHP 解释器的行为。这些选项包括执行脚本、直接运行代码、启动内置开发服务器、查看配置信息等,是 PHP 开发和运维的重要工具。

常用选项速查

  • php script.php — 执行脚本文件
  • php -r 'code' — 直接执行 PHP 代码
  • php -S localhost:8000 — 启动内置 Web 服务器
  • php -i — 显示 PHP 配置信息
  • php -m — 列出已加载模块

基础概念

CLI vs CGI 模式

特性CLI 模式CGI/FPM 模式
无超时限制默认无超时max_execution_time
输出目标STDOUT响应 body
工作目录当前目录脚本目录
$_SERVER精简完整 HTTP 信息
内存限制通常更大默认 128MB
HTTP 头不发送通过 header() 发送

选项分类

类别选项说明
执行-f, -r, -B, -E脚本执行与代码预处理
服务器-S, -t内置 Web 服务器
配置-d, -c, -n, -aini 设置与加载
信息-i, -m, -v, -l查看模块与配置
语法-l, --syntax-check语法检查

语法与代码

基本执行选项

bash
# -f — 执行文件(默认行为,可省略)
php -f script.php
php script.php          # 等同

# -r — 直接执行 PHP 代码(注意: 使用 PHP 标签)
php -r 'echo "Hello, World!\n";'
php -r 'echo date("Y-m-d H:i:s") . "\n";'

# -B — 在执行脚本前执行 PHP 代码
php -B 'define("APP_ENV", "cli");' script.php

# -E — 在执行脚本后执行 PHP 代码
php -E 'echo "Memory: " . memory_get_peak_usage(true) . "\n";' script.php

# 组合使用 — 脚本执行前后进行配置
php -B 'error_reporting(E_ALL);' -E 'echo "Done.\n";' script.php

内置开发服务器

bash
# -S — 启动内置 Web 服务器(PHP 5.4+)
php -S localhost:8000
php -S 127.0.0.1:8080
php -S 0.0.0.0:9000           # 监听所有接口
php -S [::]:8000               # 监听 IPv6

# -t — 指定文档根目录
php -S localhost:8000 -t public/
php -S localhost:8000 -t /var/www/html

# router.php — 自定义路由脚本
php -S localhost:8000 router.php

# router.php 示例
if (php_sapi_name() === 'cli-server') {
    // 内置服务器路由逻辑
    $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
    $file = __DIR__ . '/public' . $uri;

    if ($uri !== '/' && file_exists($file) && !is_dir($file)) {
        return false; // 交由服务器处理静态文件
    }

    // 所有其他请求转发到 index.php
    require __DIR__ . '/public/index.php';
}

配置选项

bash
# -d — 覆盖 php.ini 设置
php -d display_errors=1 -d error_reporting=E_ALL script.php
php -d memory_limit=512M -d max_execution_time=0 script.php
php -d extension=redis script.php  # 加载扩展

# -c — 指定 php.ini 文件路径
php -c /etc/php/custom.ini script.php
php -c /etc/php/cli/ script.php    # 指定 ini 目录

# -n — 不使用 php.ini(纯净模式,不加载任何 ini 配置)
php -n script.php

# -a — 交互式 shell(REPL)
php -a
# php >
# php > echo "Hello\n";
# php > $array = [1, 2, 3];
# php > print_r($array);
# php > exit

# --ini — 显示已加载的 ini 文件
php --ini
# 输出: Configuration File (php.ini) Path: /usr/local/etc/php
#        Loaded Configuration File: /usr/local/etc/php/php.ini

信息查看选项

bash
# -i — 显示完整的 PHP 信息(等同 phpinfo())
php -i
php -i | grep "mysql"
php -i | grep "redis"

# -m — 列出已加载的 PHP 模块
php -m
# 输出: [PHP Modules]
#        bcmath, calendar, Core, ctype, curl, date, dom, fileinfo, filter, ...

# -v — 显示 PHP 版本
php -v
# 输出: PHP 8.3.0 (cli) (built: Nov 21 2023 10:30:00) (NTS)

# -l — 语法检查(不执行)
php -l script.php
# 输出: No syntax errors detected in script.php
# 或: Parse error: syntax error, unexpected ';' in script.php on line 10

# --ri — 显示扩展信息
php --ri redis
php --ri mysqli
php --ri pdo_mysql

# -h — 显示帮助信息
php -h

-l 语法检查的用途

  • CI/CD 流水线中的代码质量检查
  • 编辑器保存时自动语法检查
  • 部署前的快速验证
  • 批量检查整个项目: find . -name "*.php" -exec php -l {} \;

实战示例

开发服务器脚本

bash
#!/bin/bash
# dev-server.sh — 开发服务器启动脚本

HOST="${1:-localhost}"
PORT="${2:-8000}"
DOCROOT="${3:-public}"

echo "启动开发服务器: http://{$HOST}:{$PORT}"
echo "文档根目录: {$DOCROOT}"
echo "按 Ctrl+C 停止"

php -S "${HOST}:${PORT}" -t "${DOCROOT}" -d display_errors=1 -d error_reporting=E_ALL
php
<?php
// server.php — 带路由的开发服务器
if (php_sapi_name() === 'cli-server') {
    $uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));

    // 静态文件直接返回
    $filePath = __DIR__ . '/public' . $uri;
    if ($uri !== '/' && file_exists($filePath) && !is_dir($filePath)) {
        return false;
    }

    // API 路由
    if (str_starts_with($uri, '/api/')) {
        require __DIR__ . '/public/index.php';
        return true;
    }

    // SPA fallback — 所有未匹配的请求返回 index.html
    require __DIR__ . '/public/index.html';
    return true;
}

PHP 代码执行器

bash
#!/bin/bash
# php-exec.sh — 快速执行 PHP 代码片段

# 从 stdin 读取代码
echo '<?php echo strtoupper(readline("Input: "));' | php

# 从文件读取代码
php -r "$(cat code_snippet.php)"

# 多行代码
php -r '
    $items = ["apple", "banana", "cherry"];
    foreach ($items as $item) {
        echo strtoupper($item) . "\n";
    }
'

批量语法检查

bash
#!/bin/bash
# lint-check.sh — 批量语法检查

PHP_BIN="${PHP_BIN:-php}"
ERRORS=0
TOTAL=0

# 查找所有 PHP 文件并检查语法
while IFS= read -r -d '' file; do
    TOTAL=$((TOTAL + 1))
    OUTPUT=$($PHP_BIN -l "$file" 2>&1)

    if [ $? -ne 0 ]; then
        echo "FAIL: $file"
        echo "$OUTPUT"
        ERRORS=$((ERRORS + 1))
    fi
done < <(find . -name "*.php" -not -path "*/vendor/*" -print0)

echo ""
echo "检查完成: {$TOTAL} 个文件, {$ERRORS} 个错误"

if [ $ERRORS -gt 0 ]; then
    exit 1
fi

环境检测工具

bash
#!/bin/bash
# php-env.sh — PHP 环境信息报告

echo "========== PHP 环境信息 =========="
echo ""
echo "PHP 版本:"
php -v | head -1

echo ""
echo "PHP SAPI:"
php -r 'echo PHP_SAPI . "\n";'

echo ""
echo "已加载模块数:"
php -m | grep -c "^."

echo ""
echo "关键模块检查:"
for ext in curl mbstring openssl pdo pdo_mysql redis json xml zip; do
    if php -m | grep -qi "^$ext$"; then
        echo "  ✓ $ext"
    else
        echo "  ✗ $ext (未安装)"
    fi
done

echo ""
echo "重要配置:"
php -r '
    $configs = ["memory_limit", "max_execution_time", "upload_max_filesize", "post_max_size", "date.timezone"];
    foreach ($configs as $c) {
        echo "  $c = " . ini_get($c) . "\n";
    }
'

echo ""
echo "OpCache 状态:"
php -r 'echo "OpCache: " . (function_exists("opcache_get_status") ? "已启用" : "未启用") . "\n";'

echo ""
echo "======================================"

注意事项

-r 选项的语法要求

bash
# -r 选项中的代码不需要 <?php 标签
php -r 'echo "Hello\n";'        # 正确
php -r '<?php echo "Hello\n";'  # 错误: 不需要 <?php

# 但需要处理 shell 的特殊字符
php -r 'echo "Price: $100\n";'  # 错误: $ 被 shell 解释
php -r 'echo "Price: \$100\n";' # 正确: 转义 $

# 推荐使用单引号包裹,避免 shell 变量替换
php -r 'echo getcwd() . "\n";'

# 多行代码
php -r '
    $data = json_decode(file_get_contents("config.json"), true);
    print_r($data);
'

内置服务器限制

bash
# 内置服务器限制:
# 1. 单线程 — 一次只能处理一个请求
# 2. 无 HTTPS — 仅 HTTP(需配合 nginx 反向代理)
# 3. 不适合生产环境 — 仅用于开发/测试

# 生产环境使用 Nginx + PHP-FPM:
# server {
#     listen 80;
#     root /var/www/public;
#     location / {
#         try_files $uri /index.php?$query_string;
#     }
#     location ~ \.php$ {
#         fastcgi_pass unix:/run/php/php-fpm.sock;
#         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#         include fastcgi_params;
#     }
# }

内置服务器安全

内置开发服务器默认监听所有接口(0.0.0.0 时)。确保在防火墙内使用,或绑定到 127.0.0.1。不要在生产环境中暴露内置服务器。

最佳实践

1. 项目入口脚本

bash
#!/bin/bash
# bin/run — 项目统一入口脚本

PHP_BIN="${PHP_BIN:-php}"
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"

case "$1" in
    server)
        $PHP_BIN -S "${2:-localhost:8000}" -t "${ROOT_DIR}/public"
        ;;
    test)
        $PHP_BIN -d memory_limit=512M vendor/bin/phpunit "${@:2}"
        ;;
    lint)
        find "$ROOT_DIR/src" -name "*.php" -exec $PHP_BIN -l {} \;
        ;;
    env)
        $PHP_BIN -r "phpinfo();" | less
        ;;
    modules)
        $PHP_BIN -m
        ;;
    version)
        $PHP_BIN -v
        ;;
    *)
        echo "Usage: bin/run {server|test|lint|env|modules|version}"
        exit 1
        ;;
esac

2. 常用命令速查

bash
# 语法检查所有文件
find . -name "*.php" ! -path "*/vendor/*" -exec php -l {} \; 2>&1 | grep -v "No syntax errors"

# 查看模块信息
php --ri openssl
php --ri pdo_mysql

# 快速测试代码
php -r 'var_dump(json_decode("{\"a\":1,\"b\":2}", true));'

# 启动 HTTPS 服务器(需配合 stunnel 或 mkcert)
mkcert -install
php -S localhost:8443 -t public/

# 内存分析
php -d memory_limit=1G script.php

参考链接