-
Notifications
You must be signed in to change notification settings - Fork 684
Description
What happened?
Description
I need to create some nested elements programmatically – specifically, an Address elements in an Addresses fields and some Entry elements in some Matrix fields. Here's a minimal example, triggered on Entry::EVENT_BEFORE_SAVE:
public function handleBeforeEntrySave(ModelEvent $e)
{
$entry = $e->sender;
if (!$entry->section || $entry->section->handle !== 'offers') {
return;
}
if (ElementHelper::isDraftOrRevision($entry)) {
return;
}
$entry->setFieldValue('contact', [
'sortOrder' => ['new:1'],
'entries' => [
'new:1' => [
'type' => 'contact_block',
'fields' => [
'myCustomField' => 'foobar',
],
],
],
]);
}Steps to reproduce
- In the code above, replace
offerswith any section handle,contactwith the name of a matrix field,contact_blockwith the handle of an entry type that's allowed in the Matrix fields, and thefieldsarray with some field values for that entry type. - Trigger that function on
Entry::EVENT_BEFORE_SAVE. - Modify some fields on an entry in that section and save it.
Expected behavior
I would expect my hook to always create a nested entry of type contact_block in the contact field.
Actual behavior
The hook only works if the entry form is submitted without any pending changes, i.e. if the user does not have a provisional draft for that entry.
If any field in the entry is modified (which means a provisional draft) is created, the nested field in the matrix entry is not created. I tried to find out what's going on:
- I checked with the debugger – the field value is definitely being set, even if the entry is saved from a provisional draft. It just has no visible effect.
- I tested this with an Addresses field as well. I can see the new row in the
addressesand theelementstable, but it gets adateDeletedvalue set to the same value asdateCreatedimmediately.
I think this might be an issue with the lifecycle of nested entries.
I found one workaround. If I execute the hook for drafts as well as canonical entries, it works correctly:
if ($entry->getIsRevision()) {
return;
}
But I'm not sure if that has any unintended side effects. And since the field value is still being set in the scenario above, I assume it's just a bug in Craft.
Craft CMS version
5.8.18
PHP version
8.3
Operating system and version
No response
Database type and version
No response
Image driver and version
No response