[英]CakePHP 3.x - hasMany through association - find
假設我在CookBook中有完整的設置: http : //book.cakephp.org/3.0/en/orm/associations.html
class StudentsTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Courses', [
'through' => 'CourseMemberships',
]);
}
}
class CoursesTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Students', [
'through' => 'CourseMemberships',
]);
}
}
class CoursesMembershipsTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Students');
$this->belongsTo('Courses');
}
}
Student BelongsToMany Course
Course BelongsToMany Student
id | student_id | course_id | days_attended | grade
我應該如何構建查詢以查找給定學生的課程,他的成績為==“A”?
$query = $this->Courses->find('all')
->contain(['CourseMemberships'])
->where(['CourseMemberships.student_id' => $student['id'], 'CourseMemberships.grade' => 'A']);
這不行。 我該怎么寫呢?
通常你會使用匹配 ,但是ORM似乎不支持在連接表“關聯”上匹配,因為它們在那時不是“真正的”關聯(你可能想建議作為增強 ),它們正在稍后補充道。
matching()
變通方法 什么工作是在外部查詢上使用matching()
和where()
,即
$query = $this->Courses
->find('all')
// contain needs to use `Students` instead (the `CourseMemberships`
// data can be found in the `_joinData` property of the tag),
// or dropped alltogether in case you don't actually need that
// data in your results
->contain(['Students'])
// this will do the magic
->matching('Students')
->where([
'CourseMemberships.student_id' => $student['id'],
'CourseMemberships.grade' => 'A'
]);
這將使用CourseMemberships
別名加入students
表以及courses_students
連接表,例如
INNER JOIN
students Students ON 1 = 1
INNER JOIN
courses_students CourseMemberships ON (
Courses.id = (CourseMemberships.course_id)
AND Students.id = (CourseMemberships.student_id)
)
因此可以應用條件。 這感覺就像一個不太好的解決方法。
另一種選擇是添加另一個顯式關聯(如提到的@AtaboyJosef),即連接表的hasMany
關聯(這將在稍后的時間點自動完成,但如前所述, matching()
為時已晚)。
請注意,這將要求將連接表命名為course_memberships
!
class CoursesTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Students', [
'joinTable' => 'course_memberships',
'through' => 'CourseMemberships',
]);
$this->hasMany('CourseMemberships', [
'foreignKey' => 'course_id'
]);
}
}
這樣您就可以在CourseMemberships
關聯上使用匹配
$query = $this->Courses
->find('all')
// with this solution you can also use contain for `CourseMemberships`
->contain(['CourseMemberships'])
->matching('CourseMemberships', function(\Cake\ORM\Query $query) use ($student) {
return $query->where([
'CourseMemberships.student_id' => $student['id'],
'CourseMemberships.grade' => 'A'
]);
});
應該創建一個類似的查詢
INNER JOIN course_memberships CourseMemberships ON (
CourseMemberships.student_id = 1
AND CourseMemberships.grade = 'A'
AND Course.id = (CourseMemberships.course_id)
)
這可能會更有效,因為它需要更少的選擇。
through
允許您提供要在連接表上使用的Table實例的名稱,或者提供實例本身。 這使得可以自定義連接表鍵,並允許您自定義數據透視表的行為。
使用數組語法定義更具體的關系:
class StudentsTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Courses', [
'joinTable' => 'courses',
'through' => 'CourseMemberships',
]);
}
}
class CoursesTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Students', [
'joinTable' => 'students',
'through' => 'CourseMemberships',
]);
}
}
class CoursesMembershipsTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Students', [
'foreignKey' => 'student_id',
'joinType' => 'INNER', // OR specify the type
]);
$this->belongsTo('Courses', [
'foreignKey' => 'course_id',
'joinType' => 'INNER',
]);
}
}
確保你有表courses
, students
和course_memberships
。
現在運行代碼:
$query = $this->Courses->find('all')
->contain(['CourseMemberships'])
->where(['CourseMemberships.student_id' => $student['id'], 'CourseMemberships.grade' => 'A']);
好吧,如果你真的需要與HasMany Associations
有關的東西,我很害怕。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.