Updating field values directly (without using setFieldValue) stopped working in 3.4
Execute this code:
$entry = Entry::find()->section('home')->one();
$entry->setFieldValue('heroTitle', 'field value set using setFieldValue -> works');
$entry->heroTitle = 'some directly set value -> no longer working';
Craft::$app->getElements()->saveElement($entry);
Setting field values directly like that was never supported. You have to go through setFieldValue() or setFieldValues().
@brandonkelly this is breaking the fixtures in Craft CMS core, see https://github.com/craftcms/cms/blob/3.4/src/test/fixtures/elements/ElementFixture.php#L108
Using the field: prefix in the fixture data files will fix this for now.
See this line.
Like this? 28635aebe9d0ea21ecd441bf1850cead02bd7249 😄
Let me know if I missed something though.
Just out of curiosity, what change broke this? And shouldn't it generate a deprecation warning?
I’m guessing it broke due to the new change tracking, where elements now track which field/attribute values are dirty (#4149), which is the basis of delta updating.
But it was already broken to a lesser degree. The reason you must go through setFieldValue() is so Craft knows that it needs to pass the value through the field type’s normalizeValue() method, to ensure it’s working with a normalized value. So for example this would not have worked:
$entry->myAssetsField = [100, 200];
But this would:
$entry->setFieldValue('myAssetsField', [100, 200]);
And shouldn't it generate a deprecation warning?
Ideally sure, but when you set the value like that, it’s setting a public property value directly on the ContentBehavior. Which means there’s no setter method invoked. (Which is the whole reason we don’t support this.)
@brandonkelly uhm, $entry->myAssetsField = [100, 200] worked in 3.3...
we used this a lot in our fixtures
Sorry I should clarify… yes that will work, _in the event that the field value hadn’t been normalized yet_, so Craft didn’t have a record of it being a normalized value. More specifically, this would not work:
// anything here that were to access $entry->myAssetsField
$entry->myAssetsField;
// then...
$entry->myAssetsField = [100, 200];
That probably explains why it works in our fixtures. I guess the quickest fix for our fixtures is to use the field: workaround. I'm guessing more people are going to stumble on this.
Well it’s better for things to break consistently than inconsistently right?
I’ll add a warning to the changelog though.
Most helpful comment
Well it’s better for things to break consistently than inconsistently right?
I’ll add a warning to the changelog though.