You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Codeigniter Active Record中如何在WHERE子句使用SOUNDS LIKE?

解决CodeIgniter Active Record中SOUNDS LIKE的语法错误问题

问题分析

你遇到的问题是CodeIgniter的Active Record自动把SOUNDS当成了字段名,给它加上了反引号,导致生成的SQL语句出现语法错误。从你提供的错误SQL能明显看到:

OR `name` `SOUNDS` LIKE 'technolog'

这里SOUNDS被错误地加上了反引号,但SOUNDS LIKE是MariaDB/MySQL的原生语法,根本不需要被转义或加反引号。

解决方案

要搞定这个问题,你得告诉CodeIgniter不要对SOUNDS LIKE这部分条件做转义处理,同时还要注意规避SQL注入风险,推荐两种安全的处理方式:

方法1:关闭单个条件的转义

用or_where的第二个参数FALSE,明确告诉CI不要转义当前条件:

foreach($qes as $k){
    // 第二个参数FALSE阻止CI转义这个条件
    $this->db->or_where("name SOUNDS LIKE '$k'", FALSE);
}

不过这种方式直接拼接变量$k存在SQL注入风险,如果你能确保$k已经被安全过滤,可以用;否则更推荐下面的方法。

方法2:使用查询绑定(更安全)

CodeIgniter支持查询绑定,会自动处理变量的转义,同时不会破坏SOUNDS LIKE的语法:

foreach($qes as $k){
    // 使用?作为占位符,第二个参数传入变量,CI自动处理转义
    $this->db->or_where("name SOUNDS LIKE ?", $k);
}

另外,你原代码里SOUNDEX(name) IN({$q})的写法也有SQL注入隐患,同样可以改成绑定形式:

// 假设$q是单个值,如果是多个值可以传数组
$this->db->where("SOUNDEX(name) IN(?)", $q);

修正后的完整代码

function _search($type, $q, $qes, $sort = null, $start = 0) {
    $type = strtolower($type);
    $q = strtolower($q);
    
    $this->db->select("*");
    $this->db->from("books");
    // 用绑定方式替换直接拼接,规避注入风险
    $this->db->where("SOUNDEX(name) IN(?)", $q);
    
    foreach($qes as $k){
        // 使用查询绑定处理SOUNDS LIKE,避免语法错误和注入
        $this->db->or_where("name SOUNDS LIKE ?", $k);
    }
    
    foreach($qes as $k){
        // 模糊查询也用绑定更安全
        $this->db->or_where("name LIKE ?", "%$k%");
    }
    
    $this->db->where("status", 1);
    
    if ($type != NULL) {
        $this->db->where("LOWER(type)", $type);
    }
    
    $this->db->limit(BWK_MAX_BOOK_SIZE, $start);
    
    switch ($sort) {
        case 1:
            break;
        case 2:
            $this->db->order_by("sellingPrice", "ASC");
            break;
        case 3:
            $this->db->order_by("sellingPrice", "DESC");
            break;
        case 4:
            $this->db->order_by("created", "DESC");
            break;
    }
}

验证效果

修正后生成的SQL会变成正确的形式:

SELECT * FROM `books` WHERE SOUNDEX(name) IN('t254') OR name SOUNDS LIKE 'technolog' OR name LIKE '%technologi%' AND `status` = 1 AND LOWER(type) = 'school' LIMIT 50

这样既不会有语法错误,还能避免SQL注入的风险。

内容的提问来源于stack exchange,提问作者lokesh jain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:12:50