2015-10-26 72 views
5

我認爲這是一種常見模式,但我找不到優雅的CakePHP方式。這個想法是從列表中刪除已經選擇的值。要使用從蛋糕預定一個例子:Cakephp 3 NOT IN查詢

table Students (id int, name varchar) 
table Courses (id int, name varchar) 
table CoursesMemberships (id int, student_id int, course_id int, days_attended int, grade varchar) 

所有我想要做的就是創建一個查詢,它返回一個給定的學生還沒有報名參加了課程,最有可能來填充選擇下拉。

如果我沒有使用蛋糕,我會做這樣的事情

select * from Courses where id not in 
    (select course_id from CoursesMemberships where student_id = $student_id) 

也許等效NOT EXISTS子句,或外連接弄虛作假,但你的想法。

我很難過如何在Cake中優雅地做到這一點。在我看來,這將是一個普遍的需求,但我已經研究了一段時間,並嘗試了一些查詢思路,但無濟於事。

回答

2

IMO找到最優雅的答案...使用notMatching()選項:

$data = $this->Courses->find("list") 
         ->notMatching("Students", 
         function($q) use ($student_id) { 
          return $q->where(["Students.id"=>$student_id]); 
         } 
        ); 

這是假設學生的hasMany課程和課程HasMany學生當然。

我認爲這是最優雅的答案,因爲它不依賴於瞭解任何SQL,並且代表了我試圖用Cake的語義實現的邏輯。

5

在CakePHP 3中,您可以創建NOT IN這樣的查詢。

$query = $Courses->find() 
    ->where(['id NOT IN' => $ids]); 

而在CakePHP 3中,您可以創建IN這樣的查詢。

$query = $Courses->find() 
    ->where(['id IN' => $ids]); 

您可以在CakePHP 3 Cookbook - Creating IN Clauses中閱讀。

+0

我設法使用更復雜的機制來完成這項工作(請參閱上面的註釋)。但是我一直在尋找的是一種簡單的查詢方式,而不是查詢現有記錄,將它們強制轉換爲數組,然後使用上述方法。 –

+0

看到這個例子:http://book.cakephp.org/3.0/en/orm/query-builder.html#subqueries – user3082321

9

如果你想使用子查詢,只需通過一個查詢對象的條件值,如

$subquery = $Courses->CoursesMemberships 
    ->find() 
    ->select(['CoursesMemberships.course_id']) 
    ->where(['CoursesMemberships.student_id' => $student_id]); 

$query = $Courses 
    ->find() 
    ->where([ 
     'Courses.id NOT IN' => $subquery 
    ]); 

作爲替代有也Query::notMatching()(如CakePHP的3.1),它可以用來選擇記錄偉馳相關記錄不匹配特定條件:

$query = $Courses 
    ->find() 
    ->notMatching(['CoursesMemberships' => function (\Cake\ORM\Query $query) use ($student_id) { 
     return $query 
      ->where(['CoursesMemberships.student_id' => $student_id]); 
    }]); 

參見