如何在CakePHP 3.x中的MySQL IN子句中使用多个列?

时间:2016-10-24 10:58:13

标签: php mysql arrays cakephp cakephp-3.x

我正在尝试通过CakePHP 3.x执行以下SQL,如下所述:

SELECT
 COL1,
 COL2,
 COL3
FROM
 Selections
WHERE
 ROW (COL1, COL2) NOT IN (
  ROW (1, 1),
  ROW (2, 2)
 );

我已将要过滤的值存储为数组

$filter = [[1 ,1], [2, 2]];

在CakePHP 3.x控制器中,我尝试执行以下Query:

$conditions['ROW (Selections.COL1, Selections.COL2) NOT IN'] = $filter;
$options = [
    'limit'      => 1,
    'conditions' => $conditions,
    'order'      => ['Selections.created' => 'asc']
];
debug($this->Selections->find('all', $options));
$selections = $this->Selections->find('all', $options);

由于遵循CakePHP 3.x错误,此执行导致失败:

Cannot convert value to string
InvalidArgumentException

在调试Object时,我发现它没有正确的参数类型(下面以粗体标记):

'params' => [
    ':c0' => [
        'value' => [
            (int) 0 => [
                (int) 0 => (int) 1,
                (int) 1 => (int) 1
            ],
            (int) 1 => [
                (int) 0 => (int) 2,
                (int) 1 => (int) 2
            ]
        ],
        'type' => **null**,
        'placeholder' => 'c2'
    ]
],

根据我的理解,类型应为'integer [] []',以便允许将双维数组正确转换为字符串。但是,类型为null可能会干扰正确的转换。

作为替代方案,我试图破坏$filter数组,从而将其转换为正确的字符串,其中包含正确的括号和分隔符,如下所示:

$filter[] = 'ROW '.implode(', ', [1, 1]);
$conditions['ROW (Selections.COL1, Selections.COL2) NOT IN'] = '('.implode(', ', $filter).')';

这正确地将数组转换为字符串,但CakePHP向前迈出了一步,并将生成的字符串封装在引号内。这导致以下查询在MySQL数据库服务器上执行期间抛出错误。

SELECT
 COL1,
 COL2,
 COL3
FROM
 Selections
WHERE
 ROW (COL1, COL2) NOT IN '(
  ROW (1, 1),
  ROW (2, 2)
 )';

请注意NOT IN之后和括号之前的额外报价。

我正在寻找以下解决方案之一:

  1. 有没有办法指定正确的参数类型 帮助CakePHP正确转换为double的字符串 维数组?
  2. 如果我自己尝试字符串转换,就像 如上所述,我怎样才能避免自动放置引号?
  3. 我还希望了解有关为什么CakePHP 3.x在上述情况下将参数类型指定为NULL以及可以避免这种情况的方法的其他信息。

    如果在CakePHP中有其他方法可以处理这种情况,那么试图解释它就不会没有我真诚的感谢。

1 个答案:

答案 0 :(得分:0)

使用第二种自行生成字符串的方法,解决这个问题非常容易:

$filter[] = 'ROW '.implode(', ', [1, 1]);
$conditions['ROW (Selections.COL1, Selections.COL2) NOT IN'] = '('.implode(', ', $filter).')';

第二行应替换为:

$conditions['ROW (Printouts.user_id, Printouts.receiver) NOT IN ('.implode(',',$dispatched).')'];
该死的!解决了扩展到2页的问题描述需要不到一行换行。基本上,可以避免指定条件的'key' => 'value'格式,只需将整个条件指定为'value'