CodeIgniter中应优先使用数组形式的where()防止SQL注入,where_in()要求纯数值或字符串数组,like()需按索引位置选择通配符以保障性能,复杂逻辑须用group_start()/group_end()控制AND/OR优先级。

CI(CodeIgniter)里写自定义 WHERE 条件,不是拼 SQL 字符串,而是用框架封装好的方法组合逻辑 —— 否则容易 SQL 注入、类型错乱、字段名被转义失败。
where() 传数组 vs 传字符串的区别
传数组最安全,适合多个等值条件;传字符串灵活但要自己处理引号和转义。
-
where(['status' => 'active', 'type !=' => 'draft']):自动给字符串加单引号,数字不加,!=这类操作符必须带空格写在键名里 -
where("name = 'John' AND created_at > '2024-01-01'"):全靠你自己写对引号和日期格式,created_at是 datetime 类型,必须用'YYYY-MM-DD HH:MM:SS'格式 - 混用风险高:
where(['id' => $id])->where("status = 'active'")会合并成AND,但一旦字符串里用了OR,没括号就容易优先级错乱
where_in() 和 where_not_in() 的数组要求
这两个方法只接受「纯数值或字符串数组」,不能是关联数组,也不能含 null 或空字符串。
-
where_in('user_id', [1, 2, 3])→ 生成IN (1, 2, 3),数据库直接匹配 -
where_in('email', ['a@b.com', 'c@d.com'])→ 自动加单引号,变成IN ('a@b.com', 'c@d.com') - 如果传的是
[1, null, 'abc'],CI 会把null当空字符串处理,查出来可能多出意外记录 - 空数组
[]会导致查询变成IN (),MySQL 报错,PostgreSQL 直接返回空结果 —— 必须提前判断
like() 模糊查询的三个位置参数怎么选
like() 第三个参数控制通配符放哪,直接影响索引是否生效,别默认用 'both'。
-
like('title', 'php', 'after')→title LIKE 'php%',能走索引,快 -
like('title', 'php', 'before')→title LIKE '%php',索引失效,大表慎用 -
like('title', 'php', 'both')→title LIKE '%php%',全表扫描,10 万行以上基本卡住 - 想查邮箱包含某域名?别用
like('email', '@gmail.com', 'both'),改用like('email', 'gmail.com', 'after')+where("email LIKE '%@gmail.com')"更准
多个条件混合时 AND/OR 优先级陷阱
CI 默认所有 where() 都是 AND 连接,真要用 OR,得用括号包裹或拆成子查询。
-
where('status', 'active')->or_where('role', 'admin')→WHERE status = 'active' OR role = 'admin',这是唯一支持原生 OR 的写法 -
where("(status = 'active' OR role = 'admin') AND dept = 'tech'"):括号必须手动写,CI 不帮你加 - 复杂逻辑建议分步:
$this->db->group_start()->where('status', 'active')->or_where('role', 'admin')->group_end()->where('dept', 'tech') - 漏掉
group_start()/group_end(),OR会和后面所有where平级,查出的数据远超预期
真正难的不是写对语法,而是判断哪些条件该进数组、哪些必须拆成字符串、哪些模糊查询其实该换全文索引 —— 尤其当 WHERE 里开始出现函数(如 DATE(created_at) = '2024-01-01')或类型转换时,CI 的自动处理就不可靠了。











