I'm trying to learn CakePHP and running into some issues (maybe just my misunderstanding) with the ways associations are handled. I have a RESULTS table with a composite key made of two foreign keys from tables WORKSHEETS and STUDENTS. Here are the relationships between Results, Worksheets and Students.
Results N - 1 Students
Results N - 1 Worksheets
My problem is, the scaffolded ADD page for my RESULTS table doesn't show the <select> field for STUDENTS and WORKSHEETS.
First, here is the HTML of the results/add.php page, generated by the Form->control. The two inputs for STUDENT and WORKSHEET are not Selects but hidden inputs.
<input type="hidden" name="student_id" options="(object)Cake\Datasource\ResultSetDecorator" id="student-id"/>
<input type="hidden" name="worksheet_id" options="(object)Cake\Datasource\ResultSetDecorator" id="worksheet-id"/>
<div class="input text">
<label for="result">Result</label>
<input type="text" name="result" id="result" maxlength="6"/></div>
<button type="submit">Submit</button>
Here is the scaffolded initialize() code for ResultsTable.php:
$this->setTable('results');
$this->setDisplayField(['student_id', 'worksheet_id']);
$this->setPrimaryKey(['student_id', 'worksheet_id']);
$this->addBehavior('Timestamp');
$this->belongsTo('Students', [
'foreignKey' => 'student_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Worksheets', [
'foreignKey' => 'worksheet_id',
'joinType' => 'INNER',
]);
Here is the Form Control generation in add.php (the two first lines were not even added during scaffolding).
echo $this->Form->control('student_id', ['options' => $students]);
echo $this->Form->control('worksheet_id', ['options' => $worksheets]);
echo $this->Form->control('result');
Here is the last part of the add function in the controller:
$students = $this->Results->Students->find('list', ['limit' => 200])->all();
$worksheets = $this->Results->Worksheets->find('list', ['limit' => 200])->all();
$this->set(compact('result', 'students', 'worksheets'));
StudentsTable.php initialize()
$this->setTable('students');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Ranks', [
'foreignKey' => 'rank_id',
]);
$this->belongsTo('Grades', [
'foreignKey' => 'grade_id',
'joinType' => 'INNER',
]);
$this->hasMany('Results', [
'foreignKey' => 'student_id',
]);
WorksheetsTable.php initialize()
$this->setTable('worksheets');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Subranks', [
'foreignKey' => 'subrank_id',
'joinType' => 'INNER',
]);
$this->hasMany('Results', [
'foreignKey' => 'worksheet_id',
]);
}
Some hints about why this is happening ?
Let me know if you need any kind of other information or piece of code.
PS: All other tables with belongsTo relationships were scaffolded properly and have the right <select> fields.
Debug($worksheets) output:
ROOT\templates\Results\add.php (line 8)
object(Cake\Datasource\ResultSetDecorator) id:0 {
'count' => (int) 12
}
debug($students) output:
ROOT\templates\Results\add.php (line 10)
object(Cake\Datasource\ResultSetDecorator) id:0 {
'count' => (int) 2
}
After removing ->all() from the add method in the controller, getting a query object as follows:
ROOT\templates\Results\add.php (line 10)
object(Cake\ORM\Query) id:0 {
'(help)' => 'This is a Query object, to get the results execute or iterate it.'
'sql' => 'SELECT Students.id AS Students__id, Students.name AS Students__name FROM students Students LIMIT 200'
'params' => [
]
'defaultTypes' => [
'Students__id' => 'integer',
'Students.id' => 'integer',
'id' => 'integer',
'Students__student_number' => 'string',
'Students.student_number' => 'string',
'student_number' => 'string',
'Students__name' => 'string',
'Students.name' => 'string',
'name' => 'string',
'Students__rank_id' => 'integer',
'Students.rank_id' => 'integer',
'rank_id' => 'integer',
'Students__worksheets_count' => 'integer',
'Students.worksheets_count' => 'integer',
'worksheets_count' => 'integer',
'Students__perfects_count' => 'integer',
'Students.perfects_count' => 'integer',
'perfects_count' => 'integer',
'Students__accuracy_rate' => 'integer',
'Students.accuracy_rate' => 'integer',
'accuracy_rate' => 'integer',
'Students__created' => 'date',
'Students.created' => 'date',
'created' => 'date',
'Students__modified' => 'date',
'Students.modified' => 'date',
'modified' => 'date',
'Students__email' => 'string',
'Students.email' => 'string',
'email' => 'string',
'Students__password' => 'string',
'Students.password' => 'string',
'password' => 'string',
'Students__grade_id' => 'integer',
'Students.grade_id' => 'integer',
'grade_id' => 'integer',
]
'decorators' => (int) 0
'executed' => false
'hydrate' => true
'buffered' => true
'formatters' => (int) 1
'mapReducers' => (int) 0
'contain' => [
]
'matching' => [
]
'extraOptions' => [
]
'repository' => object(App\Model\Table\StudentsTable) id:1 {
'registryAlias' => 'Students'
'table' => 'students'
'alias' => 'Students'
'entityClass' => 'App\Model\Entity\Student'
'associations' => [
(int) 0 => 'Ranks',
(int) 1 => 'Grades',
(int) 2 => 'Results',
]
'behaviors' => [
(int) 0 => 'Timestamp',
]
'defaultConnection' => 'default'
'connectionName' => 'default'
}
}
ROOT\templates\Results\add.php (line 8)
object(Cake\ORM\Query) id:0 {
'(help)' => 'This is a Query object, to get the results execute or iterate it.'
'sql' => 'SELECT Worksheets.id AS Worksheets__id FROM worksheets Worksheets LIMIT 200'
'params' => [
]
'defaultTypes' => [
'Worksheets__id' => 'integer',
'Worksheets.id' => 'integer',
'id' => 'integer',
'Worksheets__subrank_id' => 'integer',
'Worksheets.subrank_id' => 'integer',
'subrank_id' => 'integer',
'Worksheets__link' => 'string',
'Worksheets.link' => 'string',
'link' => 'string',
'Worksheets__created' => 'date',
'Worksheets.created' => 'date',
'created' => 'date',
'Worksheets__modified' => 'date',
'Worksheets.modified' => 'date',
'modified' => 'date',
]
'decorators' => (int) 0
'executed' => false
'hydrate' => true
'buffered' => true
'formatters' => (int) 1
'mapReducers' => (int) 0
'contain' => [
]
'matching' => [
]
'extraOptions' => [
]
'repository' => object(App\Model\Table\WorksheetsTable) id:1 {
'registryAlias' => 'Worksheets'
'table' => 'worksheets'
'alias' => 'Worksheets'
'entityClass' => 'App\Model\Entity\Worksheet'
'associations' => [
(int) 0 => 'Subranks',
(int) 1 => 'Results',
]
'behaviors' => [
(int) 0 => 'Timestamp',
]
'defaultConnection' => 'default'
'connectionName' => 'default'
}
}
try forcing the type to select to the form control