Cakephp 3不在查询中

时间:2015-10-26 18:52:52

标签: cakephp orm cakephp-3.0

我认为这是一种常见的模式,但我无法找到优雅的CakePHP方式。我们的想法是从列表中删除已经选择的值。要使用Cake书中的一个例子:

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)

我想要做的就是创建一个查询,返回给定学生尚未注册的课程,最有可能填充选择下拉列表。

如果我没有使用Cake,我会做

之类的事情
select * from Courses where id not in 
    (select course_id from CoursesMemberships where student_id = $student_id)

或者可能是等效的NOT EXISTS子句,或外连接技巧,但你明白了。

我很难在Cake中如何优雅地做到这一点。在我看来,这将是一个共同的需求,但我已经研究了一段时间,并尝试了一些查询的想法,但没有用。

3 个答案:

答案 0 :(得分:12)

如果要使用子查询,只需将查询对象作为条件值传递,如

$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]);
    }]);

另见

答案 1 :(得分: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中阅读相关内容。

答案 2 :(得分:2)

找到IMO最优雅的答案...使用notMatching()选项:

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

这假设学生HasMany课程和课程当然有很多学生。

我认为这是最优雅的答案,因为它不依赖于了解任何SQL,并且代表了我尝试使用Cake语义实现的逻辑。