安全构建sql查询需先校验空值与类型:字符串用trim()+!empty()过滤,数值用filter_var()校验;or条件须用group_start()/group_end()显式分组;分页需启用page_query_strings并动态拼接url参数。

直接堆 where() 调用多条件,90% 会出 SQL 错误或逻辑错乱——空值没跳过、OR 优先级混乱、分页丢参,全是高频线上事故点。
怎么安全跳过空值或无效参数
用户没填的字段(比如价格区间留空、关键词是空字符串),不能让 where('price >=', '') 进入查询。MySQL 会把它当 0 或隐式转成空字符串,导致全表扫描甚至逻辑错乱。
- 所有输入必须先走
trim()+!empty()判断:$kw = trim($this->input->get('kw'));后立刻if (!empty($kw)) { $this->db->like('title', $kw); } - 数值型字段(如
cat_id、status)必须用filter_var($val, FILTER_VALIDATE_INT)或is_numeric()校验,避免传入'1 OR 1=1'这类注入片段 - 字符串字段别手动拼 SQL,交给 Query Builder:用
$this->db->escape_str($val)或直接传给where()(它默认开启自动转义)
如何写对 OR 条件,尤其是跨字段搜索
or_like() 看似方便,但它的默认行为是把所有后续 or_* 都塞进同一个 OR 组,容易和已有 AND 条件冲突。比如你本想查「(标题含关键词 OR 描述含关键词) AND 分类=2」,结果生成的是「标题含关键词 OR 描述含关键词 AND 分类=2」,优先级错乱。
- 必须用
group_start()/group_end()显式括起 OR 部分:$this->db->group_start()->like('title', $kw)->or_like('description', $kw)->group_end() - 多个关键词(如“手机 5G”)要拆开处理:先
explode(' ', $kw),再对每个词循环执行group_start()→like()→or_like()→group_end() - 前缀匹配(如品牌名“Apple”开头)显式传第三个参数:
like('brand', 'Apple', 'before'),否则默认是前后模糊%Apple%
分页时怎么保留所有筛选参数
CodeIgniter 默认分页只认 URI 段(如 /search/2),但筛选参数基本都在 query string(?cat=2&kw=phone)里。不改配置,一翻页就丢条件。
- 必须启用
$config['page_query_strings'] = TRUE;,让分页类识别per_page这类参数 -
$config['base_url']不能写死路径,得动态拼:base_url('search') . '?' . http_build_query(array_diff($_GET, ['per_page'])) - 控制器开头加
$_GET = array_map('trim', $_GET);,否则空格会导致http_build_query()生成带%20的 URL,前端可能解析失
最常被忽略的是 group_start() 的嵌套层级和 array_diff() 中漏掉其它分页键(比如 page 和 per_page 都得排除)。一个括号错位,整条 WHERE 就跑偏;一个键没剔除,翻页链接就会带脏参。











