I understand that by default, the save() method will save one level of associations
https://book.cakephp.org/4/en/orm/saving-data.html#saving-with-associations
However, I have a situation where associated data is updated but no saved.
My model Form28s has these associations
$this->hasMany('Form28Instructors', [
'dependent' => true,
'foreignKey' => 'form28_id'
]);
$this->hasMany('MemberBadges', [
'dependent' => true,
'foreignKey' => 'form28_id'
]);
When a MemberBadge is saved, in the afterSave I call a function that updates the Form28 and associated data
$this->Form28s->updatePoints($entity->form28_id);
The updatePoints function will load the Form28 associated with the badge
$form28 = $this->get($id, [
'contain' => [
'Badges',
'MemberBadges',
'Form28Instructors'
]
]);
{LOGIC CUT OUT TO CALCULATE AND UPDATE POINTS}
// Save Form 28 and Associated Tables
$this->save($form28);
The points field in the Form28 updates correctly, however the Form28Instructors do not have their assigned points updated. I’ve checked and the entity is updated, but not saved. I see the fields in the entity are updated, just not saved
form28_instructors: array:1 [â–Ľ
0 => &5 App\Model\Entity\Form28Instructor {#1136 â–Ľ
#_accessible: array:9 [â–Ľ
"created" => true
"modified" => true
"created_by" => true
"modified_by" => true
"form28_id" => true
"member_id" => true
"instructor_efficiency_points" => true
"form28" => true
"member" => true
]
#_fields: array:8 [â–Ľ
"id" => 22
"created" => Cake\I18n\FrozenTime @1622330265 {#1117 â–¶}
"modified" => Cake\I18n\FrozenTime @1622575642 {#1103 â–¶}
"created_by" => 2
"modified_by" => 2
"form28_id" => 10
"member_id" => 3
"instructor_efficiency_points" => 5.0
]
#_original: array:1 [â–Ľ
"instructor_efficiency_points" => 0
]
#_hidden: []
#_virtual: []
#_dirty: array:1 [â–Ľ
"instructor_efficiency_points" => true
]
#_new: false
#_errors: []
#_invalid: []
#_registryAlias: "Form28Instructors"
ndm
April 22, 2023, 4:04pm
2
You should show all the debug output for $form28
, it might hold important information. The cut code might have valuable info too, as not every way of assigning data is equal. Also, evaluate the return value of the save()
call, and additionally debug $form28
again after that call.
Also make sure that the schema cache is up to date, ie clear it (bin/cake schema_cache clear
).
Thanks, I’ve checked the schema but no change Debug output is below
App\Model\Entity\Form28 Object
(
[id] => 10
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2017-09-02 14:45:24.000000
[timezone_type] => 3
[timezone] => UTC
)
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2023-04-23 04:31:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] =>
[modified_by] => 2
[file_number] => TE145
[unit_id] => 198
[badge_id] => 1
[workbook_reference] =>
[planned_exam_date] =>
[actual_exam_date] =>
[submit_date] => Cake\I18n\FrozenDate Object
(
[date] => 2017-09-02 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[dispatch_date] =>
[complete_date] => Cake\I18n\FrozenDate Object
(
[date] => 2017-11-06 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[examiner_id] => 3
[supervisor_id] =>
[form28_status_id] => 2
[instructor_efficiency_points] => 5
[squadron_trophy_points] => 1
[notes] =>
[form28_instructor_count] => 2
[member_badge_count] => 2
[member_badge_count_pass] => 1
[member_badge_count_fail] => 0
[form28_instructors] => Array
(
[0] => App\Model\Entity\Form28Instructor Object
(
[id] => 22
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2021-05-29 23:17:45.000000
[timezone_type] => 3
[timezone] => UTC
)
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2023-04-23 01:56:59.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 2
[modified_by] => 2
[form28_id] => 10
[member_id] => 3
[instructor_efficiency_points] => 3
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[form28_id] => 1
[member_id] => 1
[instructor_efficiency_points] => 1
[form28] => 1
[member] => 1
)
[[dirty]] => Array
(
[instructor_efficiency_points] => 1
)
[[original]] => Array
(
[instructor_efficiency_points] => 5
)
[[virtual]] => Array
(
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => Form28Instructors
)
[1] => App\Model\Entity\Form28Instructor Object
(
[id] => 25
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2023-04-23 03:52:59.000000
[timezone_type] => 3
[timezone] => UTC
)
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2023-04-23 03:59:07.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 2
[modified_by] => 2
[form28_id] => 10
[member_id] => 6
[instructor_efficiency_points] => 3
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[form28_id] => 1
[member_id] => 1
[instructor_efficiency_points] => 1
[form28] => 1
[member] => 1
)
[[dirty]] => Array
(
[instructor_efficiency_points] => 1
)
[[original]] => Array
(
[instructor_efficiency_points] => 1
)
[[virtual]] => Array
(
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => Form28Instructors
)
)
[member_badges] => Array
(
[0] => App\Model\Entity\MemberBadge Object
(
[id] => 21
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2017-11-06 12:21:18.000000
[timezone_type] => 3
[timezone] => UTC
)
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2023-04-23 04:31:28.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 3
[modified_by] => 2
[member_id] => 11
[badge_id] => 1
[form28_id] => 10
[practical_book_mark] =>
[scrap_book_mark] =>
[questionnaire_mark] =>
[exam_mark] => 100
[honours] => 1
[rpl_awarded] =>
[issuance_status_id] => 1
[date_of_issue] => Cake\I18n\FrozenDate Object
(
[date] => 2017-11-06 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[authority_card_number] => TASE178/17
[eligible_for_points] => 1
[missing_badge_id] =>
[notes] => My Notes.
[total_marks] => 100
[age_at_issue] => 5.45
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[member_id] => 1
[badge_id] => 1
[form28_id] => 1
[practical_book_mark] => 1
[scrap_book_mark] => 1
[questionnaire_mark] => 1
[exam_mark] => 1
[honours] => 1
[rpl_awarded] => 1
[issuance_status_id] => 1
[date_of_issue] => 1
[authority_card_number] => 1
[eligible_for_points] => 1
[missing_badge_id] => 1
[notes] => 1
[member] => 1
[badge] => 1
[form28] => 1
[issuance_status] => 1
)
[[dirty]] => Array
(
)
[[original]] => Array
(
)
[[virtual]] => Array
(
[0] => total_marks
[1] => age_at_issue
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => MemberBadges
)
[1] => App\Model\Entity\MemberBadge Object
(
[id] => 22
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2017-11-06 12:21:42.000000
[timezone_type] => 3
[timezone] => UTC
)
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2021-06-01 19:27:22.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 3
[modified_by] => 3
[member_id] => 3
[badge_id] => 1
[form28_id] => 10
[practical_book_mark] =>
[scrap_book_mark] =>
[questionnaire_mark] =>
[exam_mark] => 99
[honours] => 1
[rpl_awarded] =>
[issuance_status_id] => 1
[date_of_issue] => Cake\I18n\FrozenDate Object
(
[date] => 2017-11-06 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[authority_card_number] => TASE179/17
[eligible_for_points] =>
[missing_badge_id] =>
[notes] =>
[total_marks] => 99
[age_at_issue] => 5.45
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[member_id] => 1
[badge_id] => 1
[form28_id] => 1
[practical_book_mark] => 1
[scrap_book_mark] => 1
[questionnaire_mark] => 1
[exam_mark] => 1
[honours] => 1
[rpl_awarded] => 1
[issuance_status_id] => 1
[date_of_issue] => 1
[authority_card_number] => 1
[eligible_for_points] => 1
[missing_badge_id] => 1
[notes] => 1
[member] => 1
[badge] => 1
[form28] => 1
[issuance_status] => 1
)
[[dirty]] => Array
(
)
[[original]] => Array
(
)
[[virtual]] => Array
(
[0] => total_marks
[1] => age_at_issue
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => MemberBadges
)
)
[badge] => App\Model\Entity\Badge Object
(
[id] => 1
[created] =>
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2017-06-03 12:53:17.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 2
[modified_by] => 2
[name] => General Proficiency Class 6
[abbreviation] => GP6
[badge_group_id] => 1
[badge_section_id] => 1
[badge_subject_id] => 1
[badge_type_id] => 1
[no_assessment] =>
[rpl_eligible] =>
[not_available] =>
[pre_requisite_badge_id] =>
[pass_mark] => 50
[instructor_efficiency_points] => 5
[squadron_trophy_points] => 1
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[name] => 1
[abbreviation] => 1
[badge_group_id] => 1
[badge_section_id] => 1
[badge_subject_id] => 1
[badge_type_id] => 1
[no_assessment] => 1
[rpl_eligible] => 1
[not_available] => 1
[pre_requisite_badge_id] => 1
[pass_mark] => 1
[instructor_efficiency_points] => 1
[squadron_trophy_points] => 1
[badge_group] => 1
[badge_section] => 1
[badge_subject] => 1
[badge_type] => 1
[badge] => 1
[aviation_experience_classes] => 1
[diploma_badges] => 1
[form28s] => 1
[member_badges] => 1
)
[[dirty]] => Array
(
)
[[original]] => Array
(
)
[[virtual]] => Array
(
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => Badges
)
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[file_number] => 1
[unit_id] => 1
[badge_id] => 1
[workbook_reference] => 1
[planned_exam_date] => 1
[actual_exam_date] => 1
[submit_date] => 1
[dispatch_date] => 1
[complete_date] => 1
[examiner_id] => 1
[supervisor_id] => 1
[form28_status_id] => 1
[instructor_efficiency_points] => 1
[squadron_trophy_points] => 1
[notes] => 1
[form28_instructor_count] => 1
[member_badge_count] => 1
[member_badge_count_pass] => 1
[member_badge_count_fail] => 1
[unit] => 1
[badge] => 1
[member] => 1
[form28_status] => 1
[form28_instructors] => 1
[member_badges] => 1
)
[[dirty]] => Array
(
[instructor_efficiency_points] => 1
[squadron_trophy_points] => 1
[member_badge_count] => 1
[member_badge_count_pass] => 1
[member_badge_count_fail] => 1
)
[[original]] => Array
(
[member_badge_count_pass] => 2
[member_badge_count_fail] => 2
)
[[virtual]] => Array
(
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => Form28s
)
App\Model\Entity\Form28 Object
(
[id] => 20
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2019-05-21 21:35:55.000000
[timezone_type] => 3
[timezone] => UTC
)
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2023-04-23 04:31:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 6
[modified_by] => 2
[file_number] => TE151
[unit_id] => 198
[badge_id] => 129
[workbook_reference] =>
[planned_exam_date] => Cake\I18n\FrozenDate Object
(
[date] => 2019-05-31 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[actual_exam_date] =>
[submit_date] => Cake\I18n\FrozenDate Object
(
[date] => 2019-08-10 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[dispatch_date] =>
[complete_date] => Cake\I18n\FrozenDate Object
(
[date] => 2019-08-10 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[examiner_id] => 3
[supervisor_id] =>
[form28_status_id] => 2
[instructor_efficiency_points] => 20
[squadron_trophy_points] => 15
[notes] =>
[form28_instructor_count] =>
[member_badge_count] => 1
[member_badge_count_pass] => 1
[member_badge_count_fail] => 0
[form28_instructors] => Array
(
)
[member_badges] => Array
(
[0] => App\Model\Entity\MemberBadge Object
(
[id] => 39
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2019-08-10 19:18:57.000000
[timezone_type] => 3
[timezone] => UTC
)
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2023-04-23 04:31:29.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 2
[modified_by] => 2
[member_id] => 11
[badge_id] => 129
[form28_id] => 20
[practical_book_mark] =>
[scrap_book_mark] =>
[questionnaire_mark] =>
[exam_mark] => 100
[honours] =>
[rpl_awarded] =>
[issuance_status_id] => 1
[date_of_issue] => Cake\I18n\FrozenDate Object
(
[date] => 2019-08-10 00:00:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[authority_card_number] => TASE192/23
[eligible_for_points] => 1
[missing_badge_id] =>
[notes] =>
[total_marks] => 100
[age_at_issue] => 3.7
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[member_id] => 1
[badge_id] => 1
[form28_id] => 1
[practical_book_mark] => 1
[scrap_book_mark] => 1
[questionnaire_mark] => 1
[exam_mark] => 1
[honours] => 1
[rpl_awarded] => 1
[issuance_status_id] => 1
[date_of_issue] => 1
[authority_card_number] => 1
[eligible_for_points] => 1
[missing_badge_id] => 1
[notes] => 1
[member] => 1
[badge] => 1
[form28] => 1
[issuance_status] => 1
)
[[dirty]] => Array
(
)
[[original]] => Array
(
)
[[virtual]] => Array
(
[0] => total_marks
[1] => age_at_issue
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => MemberBadges
)
)
[badge] => App\Model\Entity\Badge Object
(
[id] => 129
[created] =>
[modified] => Cake\I18n\FrozenTime Object
(
[date] => 2017-06-03 13:05:54.000000
[timezone_type] => 3
[timezone] => UTC
)
[created_by] => 2
[modified_by] => 2
[name] => Aircraft Radio Class 1
[abbreviation] => AR1
[badge_group_id] => 6
[badge_section_id] => 1
[badge_subject_id] => 3
[badge_type_id] => 1
[no_assessment] =>
[rpl_eligible] => 1
[not_available] =>
[pre_requisite_badge_id] => 28
[pass_mark] => 70
[instructor_efficiency_points] => 20
[squadron_trophy_points] => 15
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[name] => 1
[abbreviation] => 1
[badge_group_id] => 1
[badge_section_id] => 1
[badge_subject_id] => 1
[badge_type_id] => 1
[no_assessment] => 1
[rpl_eligible] => 1
[not_available] => 1
[pre_requisite_badge_id] => 1
[pass_mark] => 1
[instructor_efficiency_points] => 1
[squadron_trophy_points] => 1
[badge_group] => 1
[badge_section] => 1
[badge_subject] => 1
[badge_type] => 1
[badge] => 1
[aviation_experience_classes] => 1
[diploma_badges] => 1
[form28s] => 1
[member_badges] => 1
)
[[dirty]] => Array
(
)
[[original]] => Array
(
)
[[virtual]] => Array
(
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => Badges
)
[[new]] =>
[[accessible]] => Array
(
[created] => 1
[modified] => 1
[created_by] => 1
[modified_by] => 1
[file_number] => 1
[unit_id] => 1
[badge_id] => 1
[workbook_reference] => 1
[planned_exam_date] => 1
[actual_exam_date] => 1
[submit_date] => 1
[dispatch_date] => 1
[complete_date] => 1
[examiner_id] => 1
[supervisor_id] => 1
[form28_status_id] => 1
[instructor_efficiency_points] => 1
[squadron_trophy_points] => 1
[notes] => 1
[form28_instructor_count] => 1
[member_badge_count] => 1
[member_badge_count_pass] => 1
[member_badge_count_fail] => 1
[unit] => 1
[badge] => 1
[member] => 1
[form28_status] => 1
[form28_instructors] => 1
[member_badges] => 1
)
[[dirty]] => Array
(
[instructor_efficiency_points] => 1
[squadron_trophy_points] => 1
[member_badge_count] => 1
[member_badge_count_pass] => 1
[member_badge_count_fail] => 1
)
[[original]] => Array
(
[member_badge_count_fail] => 1
)
[[virtual]] => Array
(
)
[[hasErrors]] =>
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => Form28s
)
ndm
April 23, 2023, 2:07pm
4
Well there you have it, the form28_instructors
field is not marked as dirty, hence it will not be saved. So it comes down to how you’re assigned the data.
1 Like
Basically, I’m assigning the data by running a foreach loop on $form28->form28_instructors and updating the value to the new assigned.
Whilst the field in the associated form28_instructor entity is updated and “dirty”, I’m guessing the form28 doesn’t know the associated record is changed, and to save it. I assumed it would check (don’t assume )
[[dirty]] => Array
(
[instructor_efficiency_points] => 1
)
After adding a setDirty on the associated entity it’s working now.
$form28->setDirty('form28_instructors');
Thanks - have the basic down pat and this was a more complex change generated in the afterSave