<p>必须用 mysqli 或 PDO 连接数据库,禁用已移除的 mysql_* 函数;CLI 下需显式配置、启用扩展、处理特殊字符、使用预处理防注入、手动管理事务与日志。</p>

用 mysqli 或 PDO 连接数据库,别用 mysql_* 函数
PHP 命令行(CLI)环境下不能用已废弃的 mysql_connect 等函数,它们在 PHP 7.0+ 中已被彻底移除。必须选 mysqli(面向过程或面向对象)或 PDO(推荐,支持预处理、多数据库切换)。CLI 模式下没有超时中断、没有输出缓冲干扰,但也不会自动加载 Web 环境的配置,所有连接参数得显式写死或从环境变量读取。
常见错误现象:Call to undefined function mysql_connect();或者连上后查不到数据——其实是 CLI 的 php.ini 和 Web 的不是同一份,extension=mysqli 可能没启用。
- 检查 CLI 的 PHP 配置:运行
php -i | grep "Loaded Configuration File",确认mysqli或pdo_mysql在extension=行已开启 - 连接失败时优先打印
$mysqli->connect_error或$pdo->errorInfo(),CLI 不会静默吞错 - 密码含特殊字符(如
@、/)时,用urlencode()处理再拼进 DSN,否则PDO会解析失败
CLI 脚本里执行 SQL 要注意事务和自动提交
Web 请求通常短平快,而 CLI 脚本可能跑几分钟甚至几小时。默认情况下,mysqli 和 PDO 都开启自动提交(AUTOCOMMIT=1),但批量插入/更新时关掉它能提升数倍性能,也避免中途失败导致部分写入。
容易踩的坑:脚本异常退出时没回滚,留下脏数据;或忘记手动 commit(),结果什么都没存进去。
立即学习“PHP免费学习笔记(深入)”;
- 用
$pdo->beginTransaction()开启事务,出错时调$pdo->rollback(),成功后$pdo->commit() - 大批量操作(如导入 10 万行)建议每 1000 条
commit()一次,防内存溢出或锁表太久 - CLI 下不响应用户输入,所以别写
if (confirm("确定删除?"))这类逻辑——直接加argv参数控制,比如php script.php --dry-run
安全地传参:用预处理语句,别拼字符串
CLI 脚本常从 $argv 或 getenv() 读参数,比如 php sync.php --user-id=123。如果直接把 $argv[2] 拼进 SQL,就等于裸奔——命令行参数一样可被恶意构造。
示例错误写法:"SELECT * FROM users WHERE id = " . $argv[2] → 攻击者传 --user-id='1 OR 1=1' 就全表泄露。
- 一律用预处理:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]); - 字段名、表名不能参数化,需白名单校验,比如
in_array($table, ['users', 'orders'])再拼接 - 日期范围等复杂条件,用
DateTime解析后再绑定,别信用户传的"2024-13-01"这种非法格式
调试和日志:CLI 没浏览器控制台,得靠 var_dump 和文件写入
CLI 脚本出问题没法开 Chrome DevTools,echo 和 var_dump 是最直接的调试手段,但要注意输出内容是否被缓冲、是否混在日志里难定位。
性能差、卡住、连不上数据库——这些在 CLI 下比 Web 更难一眼看出原因。
- 开头加
ini_set('display_errors', 1); error_reporting(E_ALL);,确保报错不沉默 - 查慢查询,用
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)让错直接抛出 - 关键步骤写日志到文件:
file_put_contents('sync.log', date('Y-m-d H:i:s') . " START\n", FILE_APPEND);,别只依赖echo - 连接后立刻查一句
SELECT 1,确认不是网络或权限问题,再跑主逻辑
实际运行前,先用 php -l script.php 检查语法,再用最小数据集跑通全流程——CLI 脚本一旦上线,往往就是定时任务,出错不会有人盯着看。



















