Rog*_*lan 7 orm cakephp 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)
Run Code Online (Sandbox Code Playgroud)
我想要做的就是创建一个查询,该查询返回给定学生尚未注册的课程,最有可能填充选择下拉列表.
如果我没有使用Cake,我会做类似的事情
select * from Courses where id not in
(select course_id from CoursesMemberships where student_id = $student_id)
Run Code Online (Sandbox Code Playgroud)
或者可能是等效的NOT EXISTS子句,或外连接技巧,但你明白了.
我很难在Cake中如何优雅地做到这一点.在我看来,这将是一个普遍的需求,但我已经研究了一段时间,并尝试了一些查询的想法,但无济于事.
ndm*_*ndm 17
如果要使用子查询,只需将查询对象作为条件值传递,例如
$subquery = $Courses->CoursesMemberships
->find()
->select(['CoursesMemberships.course_id'])
->where(['CoursesMemberships.student_id' => $student_id]);
$query = $Courses
->find()
->where([
'Courses.id NOT IN' => $subquery
]);
Run Code Online (Sandbox Code Playgroud)
作为替代方案,还有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]);
});
Run Code Online (Sandbox Code Playgroud)
也可以看看
小智 5
在CakePHP 3中,您可以NOT IN像这样创建查询.
$query = $Courses->find()
->where(['id NOT IN' => $ids]);
Run Code Online (Sandbox Code Playgroud)
在CakePHP 3中,您可以创建这样的IN查询.
$query = $Courses->find()
->where(['id IN' => $ids]);
Run Code Online (Sandbox Code Playgroud)
你可以在CakePHP 3 Cookbook - Creating IN Clauses中阅读它.
发现 IMO 最优雅的答案...使用 notMatching() 选项:
$data = $this->Courses->find("list")
->notMatching("Students",
function($q) use ($student_id) {
return $q->where(["Students.id"=>$student_id]);
}
);
Run Code Online (Sandbox Code Playgroud)
当然,这假设学生有许多课程并且课程有许多学生。
我认为这是最优雅的答案,因为它不依赖于了解任何 SQL,并且代表了我试图仅使用 Cake 语义实现的逻辑。