4

Cake PHP 复杂的 find 'OR' 运算符在 null 下无法正常工作...

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
    array(
        array('NOT' => array('Person.image' => null)),
        array('NOT' => array('Person.image' => '')),
    ),
    array(
        array('NOT' => array('Person.photos' => null)),
        array('NOT' => array('Person.photos' => '')),
    )
    )
);

对应的cake sql dump输出查询如下

SELECT `Person`.`id`, `Person`.`created`, `Person`.`modified` 
FROM `people` AS `Person` WHERE `Person`.`id` IN (2, 4, 1, 23, 45, 11)  AND 
((((NOT (`Person`.`image` IS NULL)) AND (NOT (`Person`.`image` = NULL))))   OR 
(((NOT (`Person`.`photos` IS NULL)) AND (NOT (`Person`.`photos` = ''))))) 
ORDER BY FIELD(`Person`.`id`, 2, 4, 1, 23, 45, 11) ASC LIMIT 3

在 cake 条件数组中,我给出Person.image的不是nullor '',而是对应的 cake sql 输出(NOT (Person.image IS NULL)) AND (NOT (Person.image = NULL))应该是这样的(NOT (Person.image IS NULL)) AND (NOT (Person.image = ''))

这里Person.image两者都与 NULL 本身(IS NULL= NULL)进行比较,其中Person.image = NULL想要与空字符串(如Person.image = '' )进行比较。

这里'Person.image''INT''Person.photos''VARCHAR'类型,但是从当前阶段很难改变类型。

如何纠正?

4

4 回答 4

3

您不必强制使用关联数组来定义条件。您可以像这样定义它:

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
    array(
        array('NOT' => array('Person.image' => null)),
        array('NOT' => array('Person.image = "" ')),
    ),
    array(
        array('NOT' => array('Person.photos' => null)),
        array('NOT' => array('Person.photos = "" ')),
    )
    )
);
于 2012-06-12T08:16:47.370 回答
1

解释可能存在问题'Person.image <>' => null,因为它不是严格有效的 SQL(至少在 MySQL 中不是)。

MySQL 手册

您不能使用算术比较运算符(例如 =、< 或 <>)来测试 NULL。

您可以尝试用否定的空比较替换它:

array('NOT' => array('Person.image' => null))

除此之外,最后两个OR运算符什么也不做,因为每个运算符只有一个语句。您的数组是否嵌套了您所说的内容?如果您添加换行符和缩进,您的代码将变为

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
        array(
            'OR' => array(
                'Person.image <>' => null
            ),
            array(
                'Person.image <>' => ''
            )
        ),
        array(
            'OR' => array(
                'Person.photos <>' => ''
            ),
            array(
                'Person.photos <>' => null
            )
        )
    )
);

...看起来很奇怪。

完整的变化将是:

$conditions = array(
    'Person.id' => array(2, 4, 1, 23, 45, 11),
    'OR' => array(
        array(
            array('NOT' => array('Person.image' => null)),
            array('NOT' => array('Person.image' => '')),
        ),
        array(
            array('NOT' => array('Person.photos' => null)),
            array('NOT' => array('Person.photos' => '')),
        )
    )
);
于 2012-06-07T13:53:33.340 回答
1

似乎 Cake 的 null 比较取决于数据库字段类型。如果您的字段是整数类型,那么 Cake 会将 '' 重新定义为 Null。Varchars 不会被重新定义。

你能去 MySQL 并将 Person.image 类型更改为 varchar 吗?

如果是这样,请记住清除 app/tmp/cache/models 中的缓存,以便 Cake 注册更改。

更新:手动更改模式类型将强制 cake 将字段类型视为定义。所以在查询之前这样的事情会起作用:

$this->Person->_schema['image']['type']='string';
于 2012-06-11T21:04:20.883 回答
0

抱歉,我认为这些答案不是 100% 正确的,它们提供了解决方法,但没有解决方案。

问题是数据库列类型:

Person.imageINT并且Person.photosVARCHAR类型

好吧,''(空字符串)永远不是整数的有效值。我假设您NULL在列上允许了值Person.image,所以 cake 做对了!

询问整数字段是否具有空字符串的值是没有任何意义的,它只能是NULL、0、1、-1、2、-2 等(如果有符号)。

这里发生的是 cake 知道您的数据结构(注意标志 > 0DESCRIBE时的查询debug),因此它会尝试将您的语句更正为下一个有用的语句 - 测试NULL值。此外,即使您要求 MySQL(或强制 cake 这样做)查询您的数据库,也不会因为这种情况而产生任何影响(可能是因为其他情况):

SELECT * FROM table WHERE my_int_column = ''是完全合法的 SQL,但总是返回 0 结果,而SELECT * FROM table WHERE NOT(my_int_column = '')总是返回所有结果。

结论:如果您的应用程序现在可以在=''条件下运行,那么它在没有条件的情况下将完全相同。

最后说明:但是,您可以INSERT将空字符串转换为整数列,MySQL 会将其转换为0,因此您可能需要检查这些。

于 2012-07-23T00:27:13.280 回答