
本文详解如何使用 CodeIgniter 的 Query Builder 正确实现“以指定前缀(如 'tom')开头”的模糊匹配查询,避免 LIKE '%tom' 导致的全表扫描错误,并提供安全、高效、可维护的代码方案。
本文详解如何使用 codeigniter 的 query builder 正确实现“以指定前缀(如 'tom')开头”的模糊匹配查询,避免 `like '%tom'` 导致的全表扫描错误,并提供安全、高效、可维护的代码方案。
在 CodeIgniter 中实现“以某字符串开头”的数据库查询(例如查找 first_name 或 last_name 以 "tom" 开头的商户),关键在于正确使用 like() 方法及其匹配模式——默认情况下,$this->db->like('field', 'tom') 会生成 LIKE 'tom%'(即前缀匹配),这正是我们所需;而原代码中手动拼接 "%$value" 实际生成的是 LIKE '%tom'(后缀匹配),导致结果不符合预期,且存在 SQL 注入风险。
以下是推荐的优化写法(基于 CodeIgniter 3.x/4.x 兼容风格):
✅ 正确用法:使用 Query Builder + like()(前缀匹配)
// Model 中的方法
public function getMerchantName($prefix = '')
{
$this->db->select('first_name, last_name, other_names, id'); // 明确字段,避免 SELECT *
if (!empty($prefix)) {
$this->db->group_start(); // 开启括号分组:(first_name LIKE 'tom%' OR last_name LIKE 'tom%' OR other_names LIKE 'tom%')
$this->db->like('first_name', $prefix, 'after'); // 'after' 表示后加 %,即 'tom%'
$this->db->or_like('last_name', $prefix, 'after');
$this->db->or_like('other_names', $prefix, 'after');
$this->db->group_end();
}
$query = $this->db->get('tbl_merchants');
return $query->result(); // 返回对象数组,更符合 CI 惯例;如需关联数组可用 result_array()
}
? 说明:
- 第三个参数 'after' 显式指定通配符位置(默认即 'after'),确保生成 LIKE 'tom%' 而非 %tom 或 %tom%;
- or_like() 必须配合 group_start() / group_end() 使用,否则逻辑优先级错误(OR 会覆盖 AND 条件);
- 避免直接拼接 $value 到 SQL 字符串中,Query Builder 自动参数化处理,杜绝 SQL 注入。
? 原代码问题分析
- ❌ array("%$value", "%$value", "%$value") → 匹配结尾含 "tom" 的记录(如 "atom"),非“以 tom 开头”;
- ❌ 手动拼接 SQL + 变量 → 若 $value 含单引号或特殊字符,将引发语法错误或安全漏洞;
- ❌ 未限制字段,SELECT * 在大表中降低性能;
- ❌ 缺少空值校验,$value 为空时仍执行 LIKE ''%,可能返回全部数据。
✅ Controller 调用示例
// Controller
public function get_merchant_name()
{
$prefix = $this->input->get('q'); // 推荐从 GET/POST 安全获取
$prefix = trim($prefix);
$names = $this->model_merchants->getMerchantName($prefix);
// 返回 JSON(适用于 AJAX 场景)
$this->output->set_content_type('application/json')->set_output(json_encode($names));
}
? 进阶建议
- 如需不区分大小写匹配,MySQL 默认 LIKE 不区分大小写(取决于字段 collation),若需强制,可添加 BINARY 或改用 LOWER() 函数(但影响索引使用);
- 为提升性能,确保 first_name、last_name 等字段建立了前缀索引(如 INDEX(first_name(10)));
- CodeIgniter 4 用户可进一步使用 whereLike() 链式调用,语法更简洁。
遵循上述方式,即可安全、精准、高效地实现“以指定字符串开头”的多字段模糊检索。











