假设我在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']);
这不起作用。我该怎么写呢?
答案 0 :(得分:16)
通常您使用matching,但ORM似乎不支持在联接表"协会"上匹配,因为它们不是"真实" 34;那时的关联(你可能想要suggest that as an enhancement),它们将在稍后添加。
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'
]);
这将使用students
别名加入courses_students
表格和CourseMemberships
联接表格,例如
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)
)
这可能会更有效率,因为它需要较少的选择。
答案 1 :(得分:0)
public partial class PrintTasks: System.Web.UI.Page
{
public BindingList<SuperObject> mySuperObjectList = new BindingList<SuperObject>();
protected void Page_Load(object sender, EventArgs e)
{
var myObject = new SuperObject();
myObject.Name = "I";
myObject.Destination = "Love";
myObject.ActionName = "StackOverFlow";
mySuperObjectList.Add(myObject);
//What next?
}
}
允许您提供要在连接表上使用的Table实例的名称,或者提供实例本身。这样可以自定义连接表键,并允许您自定义数据透视表的行为。
使用数组语法定义更具体的关系:
through
请确保您拥有表格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
好吧,如果你真的需要与HasMany Associations
相关的东西,我很害怕。