PHP CLI增删改查需手动初始化PDO连接、解析$argv参数、强制使用预处理语句防注入、区分STDERR/STDOUT输出并规范exit码。
PHP 在 CLI 模式下做增删改查,核心不是换写法,而是换环境适配——你要手动加载数据库连接、处理命令行参数、避免 Web 环境的自动行为(比如 $_GET、$_POST、自动输出头信息),同时注意 CLI 的错误报告和退出码。
Web 环境里常把连接逻辑藏在框架或配置文件中,CLI 下得显式初始化。PDO 是最稳妥的选择,它不依赖扩展模块(如 mysql_connect 已废弃),且支持异常模式便于调试。
关键点:
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,否则 SQL 错误静默失败php.ini 的 display_errors=On 保障,要手动开 ini_set('display_errors', '1')
getenv() 或读取 .env 文件(可用 vlucas/phpdotenv)#!/usr/bin/env php
PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
} catch (PDOException $e) {
fwrite(STDERR, "数据库连接失败: " . $e->getMessage() . "\n");
exit(1);
}
PHP CLI 脚本通过 $argv 接收参数,但直接手撕容易出错(比如空值、顺序错乱)。推荐用轻量方案:symfony/console(功能全)、或干脆用 array_slice($a + 简单 switch(适合小工具)。
rgv, 1)
常见结构:
php script.php insert --name="张三" --email="z@x.com"php script.php select --id=5php script.php delete --id=3注意:CLI 下没有表单验证,所有输入都不可信,--id 必须强制转为整型,--name 要用 htmlspecialchars() 或直接走预处理语句(更安全)。
CLI 脚本常被用来批量处理数据,一旦拼接 SQL 字符串(如 "INSERT INTO user VALUES ('$name')"),遇到含单引号的用户名(如 O'Connor)就直接报错,甚至引发 SQL 注入——而 CLI 环境没人盯着日志,问题会潜伏很久。
正确做法只有一条:所有用户输入进 SQL 的地方,一律走 $pdo->prepare() + $stmt->execute()。
// ✅ 安全写法
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->execute([$name, $email]);
// ❌ 危险写法(哪怕只是测试也别这么干)
$sql = "INSERT INTO users (name, email) VALUES ('$name', '$email')";
$pdo->exec($sql);
CLI 工具要能被其他程序调用(比如 shell 脚本、CI 流程),就必须按 POSIX 规范返回退出码:exit(0) 表示成功,exit(1) 表示一般错误,exit(2) 表示用法错误。同时,错误信息必须输出到 STDERR,正常结果输出到 STDOUT,否则管道(|)和重定向(> file.txt)会混乱。
示例:
echo json_encode($row) . "\n"; → 输出到 STDOUT
fwrite(STDERR, "连接超时\n"); exit(1);
fwrite(STDERR, "用法: php script.php select --id=123\n"); exit(2);
真正麻烦的从来不是写几行 SQL,而是让每个 exit 都有意义、每条 echo 都去对地方、每次 prepare 都覆盖边界输入——这些细节在 Web 里被框架兜底了,CLI 下得自己扛。