Problem/Motivation
Once we can use property hooks, we can define entity as a property on EntityReferenceFieldItemList and use property hooks to return the referenced entity.
This will allow us to completely remove the hack added in #3565937: Workaround PHP bug with fibers and __get() because property hooks don't have the same guarding issue.
The test coverage added in there can stay - since that demonstrates that the fiber suspend isn't broken by any PHP bugs.
Since the entity property is being converted to property hooks, it might make sense to do the target_id property here as well.
Also, per Zend blog, "isset operations will hit the 'get' hook", so the get property hook will fix #3590537: Workaround PHP bug with fibers and __isset() for D12 as well.
Steps to reproduce
Proposed resolution
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
Issue fork drupal-3566626
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3566626-12.x-use-property
changes, plain diff MR !14588
Comments
Comment #5
godotislateTook a shot with property hooks for
entityin bothEntityReferenceItemandEntityReferenceItemList. I choseEntityReferenceItemoverEntityReferenceItemBase, sinceentityis defined inEntityReferenceItem::propertyDefinitionsand not the code>EntityReferenceItemBase class.I thought it also made sense to add property hooks for
target_id, even though that property isn't involved in the Fiber issue.But the test PHPCS and PHPStan configuration doesn't like property hooks:
https://git.drupalcode.org/issue/drupal-3566626/-/jobs/8312295
https://git.drupalcode.org/issue/drupal-3566626/-/jobs/8312294
I ignored these temporarily, and otherwise tests are passing.
Comment #6
godotislateNot sure about PHPStan, but looks like PHPCS support for property hooks is still in progress: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/734
Comment #7
mondrakeGot similar PHPStan error while playing with property hooks in the image system:
if I
composer remove mglaman/phpstan-drupal, the error disappears. Not necessarily a phpstan-drupal issue, anyway - could also be related tophpstan-deprecation-rules.Looks like we're having a general problem with property hooks atm.
Comment #8
mondrake#7 the issue is in
\mglaman\PHPStanDrupal\DeprecatedScope\IgnoreDeprecationsScope. That method tries to reflect property hook g/setter as if they were normal methods which they aren't apparently.Comment #9
mondrakeI proposed a PR with a fix upstream, https://github.com/mglaman/phpstan-drupal/pull/935
Comment #10
godotislateThanks for investigating!
I think the bigger challenge might be PHPCS, but one step at a time.
Comment #11
quietone commentedComment #12
godotislateRebased for conflict.
I'll push this forward to NR to see how we feel about going forward with PHPCS disabled on the file.
Comment #13
godotislateComment #14
berdirReviewed.
Comment #15
godotislateMade the requested changes. I'll confirm whether the property hooks resolve the isset thing for #3590537: Workaround PHP bug with fibers and __isset() later, but PHP documentation suggests it should.
Comment #16
berdirI verified that this fixes the test added by that issue, very nice.
Feels like this is a first step toward making the entity field API a little bit more sensible, if slightly awkward due to the phpcs issues.
My understanding is that we can't backport this as it requires PHP 8.4, but I'll comment on the other issue that we only need to add that on D11 then.
Comment #17
berdirSorry, only realized now that the EntityReferenceFieldItemList also needs to change to __get()
Comment #18
berdirAnd, do we want to add the explicit test coverage from the other issue, or do we rely on the phpcs docs which say it's covered?
Comment #19
godotislateOK, switched to using item->__get in the list class. I did this for both
target_idandentity, because calling __get() directly does not cause the fiber bug, as seen by the tests still passing.I reverted the __set change in the item, because __set in FieldItemBase looks like this:
For the
target_idandentityproperties, this is no different from callingset()directly.Also added the test from #3590537: Workaround PHP bug with fibers and __isset() to the MR here.
Comment #20
berdirLets do this. See review thread on discussions around how to implement this exactly and possible edge cases around BC. Since this applies to code that previous went to __get()/__set() magic methods, there's a BC break on what I think is an edge case, but it was supported before. There is no explicit test coverage for that in core, not for these properties at least.
This is a major only change change, I created a CR for it, we could possible formally deprecate it for all properties in an attempt to reduce all the possible combinations of ways you get and set field values, which I think is really needed.
Comment #22
catchThis looks great. It's a shame about phpcs, the author pointed out the problems supporting it before the rfc went in at all and was ignored, hopefully support will get worked out eventually.
But being able to remove the Fiber workaround makes this more than well worth it, as well as the overall simplification. I think we'll be able to do more along the same lines too.
Committed/pushed to main, thanks!
Comment #24
amateescu commentedI haven't seen this mentioned in the issue, so.. are we ok with
unset($item->target_id)throwingError: Cannot unset hooked property? It's quite a BC break with no way to add a deprecation layer, unless we do it in\Drupal\Core\Field\FieldItemBase::__unset()for everyone.Comment #25
godotislateDo people do
unset($item->target_id)commonly? We have a minor BC break already by not allowingentityortarget_idto be set to typed data properties, so we could note the unset in the same CR, advising people to use$item->target_id = NULL.Couldn't we implement __unset() in EntityReferenceFieldItemList, EntityReferenceItemBase?
We could also do deprecation layer __set() for the typed data thing in the same two classes?