有效配置需确保hostname、username、password、database和dbdriver五项全对,推荐用127.0.0.1代替localhost,dbdriver显式设为mysqli,字符集用utf8mb4,并注意动态连接需传全配置且手动管理连接生命周期。

database.php 里怎么填才算有效配置
CodeIgniter 的数据库连接不是“填完就能用”,必须确保 hostname、username、password、database 和 dbdriver 这五项全对,少一个就报 Unable to connect to your database server using the provided settings。常见错误是本地开发用 localhost 没问题,但上线后换成 IP 或域名却漏改;或者 MySQL 8+ 默认用 caching_sha2_password 认证插件,而 mysqli 驱动不兼容,得在数据库侧执行 ALTER USER 'xxx'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx';。
推荐配置写法(关键项已加注):
$db['default'] = array(
'hostname' => '127.0.0.1', // 不要用 localhost(Unix socket 路径可能冲突)
'username' => 'app_user',
'password' => 'strong_pass',
'database' => 'myapp_db',
'dbdriver' => 'mysqli', // CI3 不支持 pdo_mysql 自动 fallback,必须显式写对
'char_set' => 'utf8mb4', // 比 utf8 更安全,支持 emoji
'dbcollat' => 'utf8mb4_unicode_ci',
'db_debug' => (ENVIRONMENT !== 'production'),
'save_queries' => TRUE // 开发期留着,上线建议关掉
);要不要在 autoload.php 里自动加载 database
取决于你是否**每页都查库**。如果多数控制器都要操作数据库,加进 $autoload['libraries'] = array('database'); 省事;但如果有些页面纯静态或只调 API,自动加载反而浪费一次连接开销——CI 默认会为每个请求建立新连接,不复用。
更灵活的做法是:在需要的控制器构造函数里按需加载,比如:
public function __construct()
{
parent::__construct();
$this->load->database(); // 只有这个控制器用库,才连
}注意:$this->load->database() 在构造函数中调用,比在方法里调用更早生效,避免部分方法因未加载而报 Call to a member function query() on null。
为什么 $this->db->query() 成功了,但 $this->db->insert_id() 却返回 0
这不是 bug,而是驱动行为差异。用 mysqli 时,insert_id 依赖上一次 **INSERT/REPLACE/UPDATE** 查询;如果中间穿插了 SELECT 或事务没提交,值就会丢失。尤其在多数据库场景下,容易误用错对象。
安全做法是:插入后立刻取 ID,并确认使用的是同一个 DB 对象:
- ✅ 正确:
$this->db->insert('users', $data); $id = $this->db->insert_id(); - ❌ 错误:
$this->db->query("INSERT INTO users..."); $id = $this->db->insert_id();(query()不触发 insert_id 更新逻辑) - ⚠️ 多库陷阱:用了
$second_db = $this->load->database('second_db', TRUE),却调$this->db->insert_id()—— 这个$this->db是 default,不是 second_db
动态切换数据库时,config 数组里哪些键不能省
动态连接(比如根据租户名切库)必须传完整配置数组,不能只塞 hostname 和 database。CI 内部会校验必填字段,缺 dbdriver 直接报错;缺 char_set 可能导致中文乱码;缺 dbcollat 在某些 MySQL 版本下引发排序异常。
最简可用动态配置(其他项可沿用默认逻辑):
$dynamic_config = [
'hostname' => $host,
'username' => $user,
'password' => $pass,
'database' => $dbname,
'dbdriver' => 'mysqli',
'char_set' => 'utf8mb4',
'dbcollat' => 'utf8mb4_unicode_ci',
'db_debug' => FALSE // 动态连接建议关 debug,避免敏感信息泄露
];
$tenant_db = $this->load->database($dynamic_config, TRUE);别忘了:动态连接返回的对象是独立实例,它不会影响 $this->db,也不会被 CI 自动关闭——用完不关不报错,但连接数会悄悄涨满。










