codeigniter cli数据库连接失败主因是cli与web环境php.ini不一致:需用php --ini定位cli配置路径,启用mysqli扩展(windows写php_mysqli.dll),hostname改用'127.0.0.1'避免socket错误,并通过services::get('codeigniter')获取容器实例加载数据库。

CLI环境下数据库扩展没加载,连错都不报
CodeIgniter在Web环境能连上数据库,但CLI执行时直接报Unable to connect to your database server,甚至不显示具体错误——大概率是PHP CLI用的php.ini和Web服务器(如Apache或Nginx)加载的不是同一份。Web能连只说明扩展在Web PHP里启用了,CLI可能根本没加载mysqli或pdo_mysql。
验证方式:php -m | grep -i mysqli(Linux/macOS)或php -m | findstr mysqli(Windows)。如果没输出,就确认CLI实际加载的php.ini路径:php --ini,然后编辑对应文件,取消注释extension=mysqli(Windows下写全extension=php_mysqli.dll),并确保extension_dir指向正确的扩展目录。
常见坑:
- 改了
/etc/php/8.1/apache2/php.ini,但CLI用的是/etc/php/8.1/cli/php.ini - PHP 7.0+已移除
mysql_*函数,检查php.ini里有没有残留的extension=mysql或extension=php_mysql.dll,必须注释掉 - Docker中CLI容器未挂载或复制Web容器的
php.ini配置
CLI连接MySQL时localhost走socket导致失败
CLI脚本里用'localhost'作为数据库hostname,报错mysqli::real_connect(): (HY000/2002): No such file or directory,本质是PHP CLI尝试通过Unix socket连接,但找不到mysqld.sock路径(比如/var/run/mysqld/mysqld.sock不存在或权限不对)。
最简单有效的解法:把hostname从'localhost'改成'127.0.0.1',强制走TCP/IP协议,绕过socket路径问题。
适用场景:
- Linux服务器本地部署,MySQL socket路径不标准
- Docker Compose中PHP CLI容器与MySQL容器网络互通,但
localhost指向容器自身而非MySQL服务 - Windows WSL或跨平台开发,socket行为不一致
CI4服务容器未初始化,$this->db为null
在自定义类(比如命令行命令类或独立脚本)里调用$this->load->database()返回null,或报Call to a member function query() on null——根本原因是CI4的服务容器没启动,$this不是框架上下文实例,而是普通PHP对象。
CLI模式下不能直接用$this->load,必须先获取CI主实例:
$ci = \CodeIgniter\Services::get('codeigniter');
$ci->load->database();
$db = $ci->db;
注意:
- 不要用
get_instance()(CI3函数,CI4已废弃) - 若类继承
CodeIgniter\Controller,CLI下也不会自动注入服务,仍需手动获取容器 - 调用
$ci->load->database()后,$ci->db才是可用的DB实例,不是$this->db
MySQL 8.0+认证插件不兼容CLI连接
CLI连接报错Client does not support authentication protocol requested by server,而Web端正常——这是因为MySQL 8.0默认使用caching_sha2_password认证插件,旧版PHP(尤其mysqli扩展不支持该协议。
临时修复(开发环境):
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES;
长期方案:
- 升级PHP到7.4+,并确认
mysqli编译时启用OpenSSL支持(php -i | grep openssl) - CI配置中显式指定
['charset' => 'utf8mb4', 'encrypt' => false]避免TLS协商干扰 - 生产环境避免降级认证插件,优先升级客户端驱动
复杂点在于:Web和CLI可能用不同版本PHP,Web跑在FPM里用新版,CLI却用系统自带老版;得分别检查两处php -v和php -m输出。











