CakePHP 删除多个条件

CakePHP Delete with Multiple Conditions

这让我抓狂。为什么Cake要把简单的事情搞的过于复杂..

我希望让 Cake 生成看起来像这样的 SQL..

我希望运行的 SQL 是

DELETE `ProductVouchers` 
FROM `product_vouchers` AS `ProductVouchers`   
WHERE `ProductVouchers`.`id` = 16 
AND `ProductVouchers`.`client_id` IS NULL; 

我正在这样使用delete()

$this->ProductVouchers->delete([
    'ProductVouchers.id'=>$id,
    'ProductVouchers.client_id'=>"NULL"
]);

日志显示

DELETE `ProductVouchers` 
FROM `product_vouchers` AS `ProductVouchers`   
WHERE `ProductVouchers`.`id` IN (16, 'NULL')

正在尝试

$this->ProductVouchers->delete([
   'ProductVouchers.id'=>$id,
   'ProductVouchers.client_id'=>NULL
]);

日志显示

DELETE `ProductVouchers` 
FROM `product_vouchers` AS `ProductVouchers`   
WHERE `ProductVouchers`.`id` IN (16, NULL) 

正在尝试:

 $this->ProductVouchers->delete([
    'ProductVouchers.id'=>$id,
    'ProductVouchers.client_id IS NULL'
 ]);

日志什么都没有,更错!

编辑:

正如下面的答案所指出的,delete() 方法是不正确的,因为它只接受主键作为整数。所以使用 deleteAll()

 $this->ProductVouchers->deleteAll([       
   'ProductVouchers.id'=>$id,
   'ProductVouchers.client_id'=>'NULL'
 ]);

这也不会在日志中产生任何内容或任何错误。正在尝试:

 $this->ProductVouchers->deleteAll([
   'ProductVouchers.id'=>$id,
   'ProductVouchers.client_id'=>NULL
 ]);

这会产生...

 DELETE `ProductVouchers` 
 FROM `product_vouchers` AS `ProductVouchers`   
 WHERE `ProductVouchers`.`id` = (17)

哪个既错误又奇怪(括号的意义是什么??)

只需阅读文档,delete method only takes the identifier in the first parameter 设计为整数。

看起来 Cake 团队可能已经接受了数组格式,但只使用数组值提供给删除查询(因此每次都忽略键并使用标识符。)

我相信您正在寻找 the deleteAll method,它将接受您在问题中提供的自定义条件:

$this->ProductVouchers->deleteAll(['ProductVouchers.id'=>$id,'ProductVouchers.client_id'=>"NULL"]);

此问题与模型 ProductVouchers 模型中的一个 $belongsTo 变量有关。虽然已设置,但我无法在不将 $cascade 参数设置为 false 的情况下将条件应用于外键,如下所示:

 $this->ProductVouchers->deleteAll([
   'ProductVouchers.id'=>$id,
   'ProductVouchers.client_id IS NULL'
 ],false);

这会产生工作 SQL

DELETE `ProductVouchers` FROM `product_vouchers` AS `ProductVouchers`             
LEFT JOIN `onepulse_dev`.`clients` AS `Client`
ON (`ProductVouchers`.`client_id` = `Client`.`clients_id`)  
WHERE `ProductVouchers`.`id` = 25 AND `ProductVouchers`.`client_id` IS NULL

编辑:

按照@AD7six 的综合回答删除不必要的连接。

 $this->ProductVouchers->deleteAll([
   'ProductVouchers.id'=>$id,
   'ProductVouchers.client_id'=>NULL
 ],false);

尝试关注:

$id = 100;
$conditions = array(
    'OR' => array(
        'ProductVouchers.id' => $id,
        'ProductVouchers.client_id IS NULL'
    )
);

$this->ProductVouchers->deleteAll($conditions);

应该创建以下 SQL 查询:

SELECT `ProductVouchers`.`id` FROM `cakephp2`.`ProductVouchers` AS `product_vouchers` WHERE ((`ProductVouchers`.`id` = 100) OR (`ProductVouchers`.`client_id` IS NULL)) GROUP BY `ProductVouchers`.`id`
DELETE `ProductVouchers` FROM `cakephp2`.`ProductVouchers` AS `product_vouchers` WHERE `ProductVouchers`.`id` IN (1, 8, 100)

"IN (1, 8, 100)" 是先前调用的 SELECT 语句的结果。

Model::delete 需要一个 id

删除是一种通过主键值删除一行的方法。 Model::delete 的方法签名不期望条件:

delete( ) public

Removes record for given ID. If no ID is given, the current ID is used. Returns true on success.

Parameters

integer|string $id optional null - ID of record to delete

boolean $cascade optional true

调用传递数组时的行为是它不会以任何方式工作(在这种情况下,条件数组的数组值被理解为 ids - 并用于查找 a 要删除的记录 - 最多删除一行)。

Model::deleteAll 需要条件

deleteAll是一种按条件删除行的方法:

/**
 * Deletes multiple model records based on a set of conditions.
 *
 * @param mixed $conditions Conditions to match
 * @param bool $cascade Set to true to delete records that depend on this record
 * @param bool $callbacks Run callbacks
 * @return bool True on success, false on failure
 * @link http://book.cakephp.org/2.0/en/models/deleting-data.html#deleteall
 */
    public function deleteAll($conditions, $cascade = true, $callbacks = false) {

问题中逻辑的正确调用是:

$model->deleteAll(
    [
        'ProductVouchers.id' => 16, 
        'ProductVouchers.client_id' => null
    ],
    $cascade,
    $callbacks
);

这也不会在日志中产生任何内容或任何错误

使用 $cascade true(默认值)调用 deleteAll 意味着:

  • 查找符合条件的所有记录
  • 一个一个删除

如果没有找到符合条件的记录,则不会有删除语句。

这个条件片段:

'ProductVouchers.client_id'=>'NULL'

将生成此 sql:

WHERE ProductVouchers.client_id = 'NULL'

即它将 return 行,其中 client_id 是字符串 "NULL" - 因此没有删除语句,因为有 no 行 client_id 设置为字符串 "NULL".

哪个既错误又奇怪(括号的意义是什么??)

实际上该语句是预期的 if 有一条记录具有该主键并且 client_id 设置为空(将立即有一个 select 语句在它通过 id 和 client_id 值查找之前)。括号与功能无关,这两个语句是等价的:

DELETE FROM `product_vouchers` WHERE `ProductVouchers`.`id` = (17)
DELETE FROM `product_vouchers` WHERE `ProductVouchers`.`id` = 17

如何按条件删除?

要生成这个 sql 的等价物:

DELETE FROM `product_vouchers` AS `ProductVouchers`   
WHERE `ProductVouchers`.`id` = 16 
AND `ProductVouchers`.`client_id` IS NULL; 

简单地禁用$cascade:

$model->deleteAll(
    [
        'ProductVouchers.id' => 16, 
        'ProductVouchers.client_id' => null
    ],
    false # <- single delete statement please
);

试试这个 删除所有具有多个条件

$this->Model->deleteAll(array('Model.field_name'=>'field_value'));