CakePHP在搜索条件中覆盖相同的“字段”

时间:2013-11-11 23:22:33

标签: php cakephp cakephp-1.3

我遇到一个使用CakePHP 1.3查找信息的奇怪问题。我们以此dbschema为例:

id是int(11)PRIMARY auto_increment amount是float(10,2)NULL 状态为ENUM(已完成,已删除,待处理)

id  amount  status
1   100.00  Completed
2   100.00  Removed
3   100.00  Completed
4   100.00  Completed
5   100.00  Pending

使用Cake的find从此表中检索数据时,我使用此查询:

$this->Testtable->find('all', array(
    'conditions' => array(
        'status LIKE ' => 'Removed',
        'status LIKE ' => 'Pending',
        'status LIKE ' => 'Completed'
    )
)) 

看一下这个查询,我会假设那个Cake会返回所有符合所有条件的行(这在SQL中是完全可以接受的),但它只使用它最后一个条件并返回WHERE status LIKE 'Completed'

我运行了一个测试,它正确地返回了所有行(我知道这是一种更“正确”的方式来进行查询):

'conditions' => array(
    'status' => array('Removed', 'Pending', 'Completed')        
)

以相反的方式举例,我想返回已删除或待处理的所有行:

'conditions' => array(
    'status !=' => 'Removed',
    'status !=' => 'Pending'
)

此查询返回所有已完成已删除的行,因为它只侦听最后一个语句。我认为这种情况正在发生,因为Cake不是将这些搜索条件连接到查询中,而是基于“字段”status !=来覆盖条件。我可以通过在!=之后的任何一个条件中添加一个空格来证明这个理论,创建只有确认记录的所需结果。

有人可以告诉我为什么Cake会这样做吗?由于这是在SQL中合法的事情,我认为Cake不会允许你这么做。有人知道这个问题是否在较新版本的Cake中得到修复?

2 个答案:

答案 0 :(得分:1)

我认为这归结为这样一个事实:在一天结束时,我根据该键重新分配数组值,而实际上并不是CakePHP的错。我看了一下Cake的model.php,发现了这个:

$query = array_merge(compact('conditions', 'fields', 'order', 'recursive'), array('limit' => 1));
我跑了一个测试:

$array = array(
'conditions' => array(
    'test' => 'yes',
    'test' => 'no'
)
);

$var = 'hello';
$c = compact('array', 'var');
print_r($c);

如上所述,compact仅从no密钥接收值test。我假设使用compact将变量/数组合并到查询中会递归地将条件数组中的相似键合并到最后指定的数组中,但事实证明yes甚至没有使它成为就在现场重新定义。

我认为这是PHP的限制而不是Cake,但它仍然是我不会发生的事情,并且应该以某种方式(如果它还没有)以不同的方式完成。

  

修改

我又跑了几个测试。我在自己的数组中包含相同的条件,然后将它们与Cake的查找函数进行比较。使用compact(Cake执行),包含相同键的数组保持不变,但是使用array_merge时,第一个键将被第二个键覆盖。我想在这种情况下,Cake使用compact代替array_merge来合并其查询条件是一件非常非常好的事情。

$array = array(
    array('test' => 'yes'),
    array('test' => 'no')
);

$m = array_merge($array[0], $array[1]);
$c = compact('array');

print_r($c);
print_r($m);

结果:

Array
(
    [array] => Array
        (
            [0] => Array
                (
                    [test] => yes
                )

            [1] => Array
                (
                    [test] => no
                )

        )

)
Array
(
    [test] => no
)

虽然这显然是您从根本上编写PHP代码的一个简单问题,但在使用Cake语法编写条件会相互覆盖时,这本身并不明显......

答案 1 :(得分:1)

基本PHP:不要两次使用相同的数组键

'conditions' => array(
    'status LIKE ' => 'Removed',
    'status LIKE ' => 'Pending',
    'status LIKE ' => 'Completed'
)

应该是

'conditions' => array(
    'status LIKE' => array('Removed', 'Pending', 'Completed'),
)

对于任何其他数组键也是如此。

请注意,对阵列进行一些快速调试会发现这一点。 另请参阅大量其他stackoverflow问题以及相同的问题或其他领域,基础研究可以指向您这个方向。首先看一下可以帮助在更短的时间内解决问题。