ci3中关闭'stricton'=>false仅禁用连接时set语句,并不真正关闭mysql严格模式;真正生效需检查select @@sql_mode,且应优先修复数据或表结构而非依赖宽松模式。

CI3 中把 'stricton' => FALSE 关掉,确实能绕过 MySQL 严格模式报错,但随之而来的是数据校验变松、隐式转换增多、字段被静默截断或转成默认值——这不是“修复”,而是掩盖问题。真正要解决的不是让校验失效,而是让数据和配置协同工作。
先确认你关的是不是真有用
CodeIgniter 3 的 'stricton' 只控制是否在连接时执行 SET sql_mode = 'STRICT_TRANS_TABLES' 这条语句。它不等于关闭 MySQL 全局的 strict mode,也不影响已建立连接后的其他 SQL_MODE 设置。所以:
- 关掉
'stricton'后,仍可能因全局sql_mode包含STRICT_TRANS_TABLES而报错(尤其云数据库如阿里云 RDS 默认强制开启) - 反过来,即使开了
'stricton',如果 MySQL 层禁用了该模式,也不会报 strict 错——得看最终生效的SELECT @@sql_mode - 用
var_dump($this->db->conn_id)+SHOW VARIABLES LIKE 'sql_mode'在控制器里查一次,才能确认当前连接实际加载的模式
数据校验“失效”其实是危险信号
当你发现关了 stricton 后,INSERT INTO user (name) VALUES (NULL) 不报错、反而存成空字符串或默认值,说明:
- 对应字段是
NOT NULL但没设默认值,MySQL 在非 strict 模式下会强行补默认值(比如 '' 或 0),而不是拒绝写入 -
DATETIME字段传了'0000-00-00'或空字符串,也会被转成'0000-00-00 00:00:00'(如果允许)或静默失败 - 字符超长(比如 utf8mb4 下 varchar(10) 插入 15 个中文)会被截断,且
SHOW WARNINGS才能看到提示,CI3 默认不展示
正确做法:不关校验,改数据或结构
与其依赖宽松模式兜底,不如主动适配。三类高频场景对应处理方式:
-
NOT NULL 字段没传值:在模型层做前置判断,或给字段加默认值(如
created_at DATETIME DEFAULT CURRENT_TIMESTAMP) -
时间字段非法:用 PHP 生成标准格式(
date('Y-m-d H:i:s')),或在 CI3 的$this->db->set()前做校验 -
字符集与长度冲突:确认表字符集是
utf8mb4,字段定义留足空间(emoji 占 4 字节,10 个 emoji 就要 varchar(40))
保留 stricton,但精准放行个别字段
如果某些字段必须接受空值或模糊输入(如用户填写的“可选备注”),推荐在应用层处理,而不是全局降级校验:
- 用
$this->input->post('remark', TRUE)获取并过滤,为空时显式赋''或NULL(取决于字段是否允许 NULL) - 在模型中用
$this->db->set('remark', $remark ?: '')确保值可控 - 数据库表设计上,把这类字段明确设为
NULL并配默认值,比靠 non-strict 模式“猜意图”更可靠











