【问题标题】:CodeIgniter 3.0.0 where_not_in produces `NOT` for one column only in queryCodeIgniter 3.0.0 where_not_in 仅在查询中为一列生成“NOT”
【发布时间】:2015-10-03 20:23:52
【问题描述】:

我正在将我当前的 CodeIgniter 站点从版本 2.1.4 更新到 3.0.0,并且我正在遵循 CodeIgniter's site 中列出的文档,其中我将我的数据库驱动程序从 mysql 更新到了 mysqli。每当我尝试排除某些产品和特定品牌时,我的网站都会为我的 MySQL 数据库运行 MySQL 语法错误...

$this->db->where_not_in('product_tbl.productID', $voidProducts);
$this->db->where_not_in('product_tbl.brand', $voidBrands);

这似乎会在结果查询中的 NOT 参数周围产生额外的反引号 ( ` ),如下所示...

SELECT * FROM `product_tbl` WHERE collection IS NOT NULL AND `product_tbl`.`productID` NOT IN('1', '2', '3', '4') AND product_tbl.brand `NOT` IN('brand1', 'brand2', 'brand3') GROUP BY `collection` ORDER BY `collection` ASC 

如果我尝试直接在 MySQL 数据库上运行 SQL 查询,只要我从 NOT 关联到 products_tbl.brand 列中取出反引号,它就可以正常工作。

我有相同的 where_not_in 函数来过滤掉这家商店可能不想专门展示的任何特定产品,而且效果很好。这个问题似乎只发生在品牌专栏上。我尝试将它们按不同的顺序排列,品牌列仍然会产生相同的错误,而 productID 列不会。我尝试将品牌 where_not_in 语句注释掉,它一直有效,直到它在再次搜索品牌时在另一个模型上中断,它在品牌列上运行相同的错误,但在任何其他列上都没有,我可能会将事情分开where_not_in.

我不确定在这个问题中要完全包含哪些内容,这对诊断有帮助,但请告诉我我还应该包含哪些内容来帮助解决这个问题。非常感谢任何帮助,谢谢!

TLDR: where_not_in();为 CodeIgniter 3 中的特定列在 NOT 上产生额外的反引号。

【问题讨论】:

  • 尝试使用FALSE 作为第三个参数。虽然没有测试。
  • 做到了!非常感谢!

标签: php mysql codeigniter mysqli codeigniter-3


【解决方案1】:

更新到 3.0.1 应该可以解决这个问题(如 @JuanitoMint 所述)

但是,如果由于某种原因,您无法更新到 3.0.1(在我撰写此答案时它仍在 RC2 上),您可以执行此解决方法:

修改system/database/DB_query_builder.php,在第2355行(函数_compile_wh),添加:

// temporal fix (has already been fixed in 3.0.1)
if($matches[2] == 'NOT'){
    continue;
}

这就是整个函数的样子:

// --------------------------------------------------------------------

    /**
     * Compile WHERE, HAVING statements
     *
     * Escapes identifiers in WHERE and HAVING statements at execution time.
     *
     * Required so that aliases are tracked properly, regardless of wether
     * where(), or_where(), having(), or_having are called prior to from(),
     * join() and dbprefix is added only if needed.
     *
     * @param   string  $qb_key 'qb_where' or 'qb_having'
     * @return  string  SQL statement
     */
    protected function _compile_wh($qb_key)
    {
        if (count($this->$qb_key) > 0)
        {
            for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++)
            {
                // Is this condition already compiled?
                if (is_string($this->{$qb_key}[$i]))
                {
                    continue;
                }
                elseif ($this->{$qb_key}[$i]['escape'] === FALSE)
                {
                    $this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'];
                    continue;
                }

                // Split multiple conditions
                $conditions = preg_split(
                    '/(\s*AND\s+|\s*OR\s+)/i',
                    $this->{$qb_key}[$i]['condition'],
                    -1,
                    PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
                );

                for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++)
                {
                    if (($op = $this->_get_operator($conditions[$ci])) === FALSE
                        OR ! preg_match('/^(\(?)(.*)('.preg_quote($op, '/').')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches))
                    {
                        continue;
                    }

                    // $matches = array(
                    //  0 => '(test <= foo)',   /* the whole thing */
                    //  1 => '(',       /* optional */
                    //  2 => 'test',        /* the field name */
                    //  3 => ' <= ',        /* $op */
                    //  4 => 'foo',     /* optional, if $op is e.g. 'IS NULL' */
                    //  5 => ')'        /* optional */
                    // );

                    if ( ! empty($matches[4]))
                    {
                        $this->_is_literal($matches[4]) OR $matches[4] = $this->protect_identifiers(trim($matches[4]));
                        $matches[4] = ' '.$matches[4];
                    }
                    // temporal fix (has already been fixed in 3.0.1)
                    if($matches[2] == 'NOT'){
                        continue;
                    }

                    $conditions[$ci] = $matches[1].$this->protect_identifiers(trim($matches[2]))
                        .' '.trim($matches[3]).$matches[4].$matches[5];
                }

                $this->{$qb_key}[$i] = implode('', $conditions);
            }

            return ($qb_key === 'qb_having' ? "\nHAVING " : "\nWHERE ")
                .implode("\n", $this->$qb_key);
        }

        return '';
    }

注意:最好更新到 3.0.1,除非您有非常具体的理由不更新。

【讨论】:

    【解决方案2】:

    更新到 3.0.1 似乎摆脱了这个问题和其他问题 http://forum.codeigniter.com/thread-62548.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多