2016-08-23 45 views
3

在CakePHP 3刪除濾波,假設我想刪除所有部門有一些員工命名爲「約翰」(部門有多少員工,員工所屬部門CakePHP的3通過相關數據

最簡單的方法是過濾所有的部門,並在foreach循環刪除它們一個接一個:

$departments = $this->Departments->find() 
    ->matching('Employees', function ($q) { 
     return $q->where(['Employees.name' => 'John']); 
    }) 
    ->all(); 

foreach ($departments as $department) { 
    $this->Departments->delete($department); 
} 

這將導致一個SELECT查詢加上每條記錄DELETE查詢。我希望只有一個查詢被數據庫發送和執行。事情是這樣的:

DELETE Departments 
FROM departments Departments 
INNER JOIN employees Employees ON 
    Employees.department_id = Departments.id 
    AND Employees.name = 'John'; 

閱讀中,我發現三種方式來刪除記錄文檔:

有沒有一種優雅的方式來使用CakePHP 3和ORM獲取我的查詢?

回答

0

deleteAll只是圍繞

$this->Departments->query() 
    ->delete() 
    ->where([...]) 
    ->execute(); 

一個包裹所以我雖然是,以類似的方式,將有可能做到:

$departments = $this->Departments->query() 
    ->delete() 
    ->matching('Employees', function ($q) { 
     return $q->where(['Employees.name' => 'John']); 
    }) 
    ->execute(); 

但在這種情況下,你會發現,匹配條件被忽略。我看到有一個開放的ticket有關

如果你想只使用兩個查詢,你可以做一個查詢檢索所有的ID和刪除所有在第二個查詢:

$departments_ids = $this->Departments->find() 
    ->select(['id']) 
    ->matching('Employees', function ($q) { 
     return $q->where(['Employees.name' => 'John']); 
    }) 
    ->toArray(); 

$this->Departments->deleteAll(['id' => $departments_ids ]); 

導致在類似的東西:

DELETE FROM departments WHERE id IN 
(
    // id list here 
) 

另一種解決方案可以將您的內部聯接轉換爲子查詢。實際上你想要刪除幾乎有一個名爲John的員工的所有部門。

$employees = $this->Departments->Employees->find() 
    ->select(['department_id']) 
    ->distinct() 
    ->where(['Employees.name' => 'John']); 

$departments = $this->Departments->query() 
    ->delete() 
    ->where(['id IN' => $employees]) 
    ->execute(); 
+0

謝謝@arilia。實際上,爲了獲得這個查詢,你應該把''id'=> $ departments'改成''id IN'=> $ departments',否則你得到的是一個等號「=」。另一方面,該查詢返回[1093 mysql錯誤](http://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-條款)。 – pperejon

+0

無論如何,根據[文檔](http://dev.mysql.com/doc/refman/5.6/en/update.html),生成的SQL查詢仍然是錯誤的,他們說_您無法更新表並從中進行選擇子查詢中的同一張表._ – pperejon

+0

我對此不瞭解。我將編輯或刪除我的答案 – arilia

0

兩件事情:

第一:我建議的方案是不正確

我的真實情況要複雜得多,所以我做了著名的員工部門爲例的情況。我犯了一個錯誤:我需要的是刪除屬於某個部門的所有員工。我想從相關表的基於表的條件中刪除數據。

事實上,你不能刪除有僱員姓名約翰的部門,因爲部門不是空的,還有約翰! :d

事情是這樣的:

-- Create structures 
CREATE TABLE IF NOT EXISTS departments (
    id int(11) NOT NULL AUTO_INCREMENT, 
    name varchar(45) NOT NULL, 
    PRIMARY KEY (id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; 

CREATE TABLE IF NOT EXISTS employees (
    id int(11) NOT NULL AUTO_INCREMENT, 
    department_id int(11) NOT NULL, 
    name varchar(45) NOT NULL, 
    PRIMARY KEY (id), 
    KEY fk_employees_department_idx (department_id) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; 

ALTER TABLE employees 
    ADD CONSTRAINT fk_employees_departments FOREIGN KEY (department_id) REFERENCES departments (id) ON DELETE NO ACTION ON UPDATE NO ACTION; 


-- Populate some data 
INSERT INTO departments (id, name) VALUES 
(1, 'Sales'), 
(2, 'TI'), 
(3, 'HHRR'); 

INSERT INTO employees (id, department_id, name) VALUES 
(1, 1, 'John'), 
(2, 1, 'Mary'), 
(3, 2, 'Mark'), 
(4, 3, 'Lorenzo'); 


-- Delete all employees that belong to the TI department (Mark should be removed) 
DELETE emp FROM employees emp 
INNER JOIN departments dep ON emp.department_id = dep.id AND dep.name = 'TI'; 

第二:你可以在CakePHP中做到這一點很容易

你可以得到以前的查詢相同的結果這樣做:

$departments = $this->Employees->Departments->find() 
     ->select(['Departments.id']) 
     ->where(['Departments.name' => 'TI']); 
    $this->Employees->deleteAll(['Employees.department_id IN' => $departments]); 

由此產生的MySQL查詢將是:

DELETE FROM employees WHERE department_id in 
(SELECT Departments.id AS `Departments__id` 
FROM departments Departments 
WHERE Departments.name = 'TI') 

......這是正確的,而且容易理解。 @arilia,你用第一個答案指出了這個方向。對不起,我對此深表歉意。