I do not understand what the or when to use the ‘through’ option.
the book (https://book.cakephp.org/3.0/en/orm/associations.html#using-the-through-option) reads that the through should be used if one wants to add extra data to the belongsToMany.
So I recreated the Tables from the book and ran a test.
Students
id | name
Courses
id | course_name
CoursesStudens
id | student_id | course_id | days_attended | grade
Created the models:
Students
class StudentsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('students');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
// $this->belongsToMany('Courses', [
// 'foreignKey' => 'student_id',
// 'targetForeignKey' => 'course_id',
// 'joinTable' => 'courses_students'
// ]);
$this->belongsToMany('Courses', [
'through' => 'CoursesStudents',
]);
}
}
Courses
class CoursesTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('courses');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
// $this->belongsToMany('Students', [
// 'foreignKey' => 'course_id',
// 'targetForeignKey' => 'student_id',
// 'joinTable' => 'courses_students'
// ]);
$this->belongsToMany('Students', [
'through' => 'CoursesStudents',
]);
}
}
And the join table:
class CoursesStudentsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('courses_students');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Students', [
'foreignKey' => 'student_id'
]);
$this->belongsTo('Courses', [
'foreignKey' => 'course_id'
]);
}
}
Ran the query:
$result = $this->Students->find('all')
->contain([
'Courses'
]);
debug($result->toArray());
Result:
(int) 1 => object(App\Model\Entity\Student) {
'id' => (int) 2,
'name' => 'Peter',
'courses' => [
(int) 0 => object(App\Model\Entity\Course) {
'id' => (int) 1,
'course_name' => 'PHP',
'_joinData' => object(App\Model\Entity\CoursesStudent) {
'id' => (int) 3,
'student_id' => (int) 2,
'course_id' => (int) 1,
'days_attended' => (int) 14,
'grade' => 'C',
'[new]' => false,
'[accessible]' => [
'*' => true,
'id' => false
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'CoursesStudents'
},
'[new]' => false,
'[accessible]' => [
'*' => true,
'id' => false
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Courses'
}
],
'[new]' => false,
'[accessible]' => [
'*' => true,
'id' => false
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Students'
}
]
Changed the through option back to the default for both tables:
$this->belongsToMany('Students', [
'foreignKey' => 'course_id',
'targetForeignKey' => 'student_id',
'joinTable' => 'courses_students'
]);
Ran the query:
(int) 1 => object(App\Model\Entity\Student) {
'id' => (int) 2,
'name' => 'Peter',
'courses' => [
(int) 0 => object(App\Model\Entity\Course) {
'id' => (int) 1,
'course_name' => 'PHP',
'_joinData' => object(App\Model\Entity\CoursesStudent) {
'id' => (int) 3,
'student_id' => (int) 2,
'course_id' => (int) 1,
'days_attended' => (int) 14,
'grade' => 'C',
'[new]' => false,
'[accessible]' => [
'*' => true,
'id' => false
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'CoursesStudents'
},
'[new]' => false,
'[accessible]' => [
'*' => true,
'id' => false
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Courses'
}
],
'[new]' => false,
'[accessible]' => [
'*' => true,
'id' => false
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Students'
}
]
Both results are exactly the same an both contain the _joinData data.
So now i am confused. Reading the book i would expect the normal/default table setting to not contain the _joinData. So when to use the through?