New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PropertyAccess] Fix checking for missing properties #54194
Conversation
Is there a way to test this? |
I think I did add tests, do you have something more in mind? |
Something must have blinded me 👀 Sorry! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the __exists()
your next RFC?
I don't think so :) |
I tested this fix but it doesn't work for me I use PhpDocExtractor to be able to denormalize objects with properties like this:
However I still get the same error when I serialize this kind objects :
User Notice: Undefined property: Proxies_CG_\App\Entity\IndicatorType::$lazyObjectState in /home/.../src/Serializer/PropertyAccessor.php on line 419 |
@alexandre-le-borgne Can you please open a new issue and provide a small example application that allows to reproduce your issue? |
@@ -411,8 +411,18 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid | |||
throw $e; | |||
} | |||
} elseif (PropertyReadInfo::TYPE_PROPERTY === $type) { | |||
if ($access->canBeReference() && !isset($object->$name) && !\array_key_exists($name, (array) $object) && !(new \ReflectionProperty($class, $name))->hasType()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why the $access->canBeReference()
check has been dropped here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes: that check was just wrong - __get
can return by reference, so this was an unrelated check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the information.
To harden the Extbase LazyLoadingProxy implementation a new test has been added with #101400, which creates a proxy directly and using ObjectAccess::getProperty() to access a property of the not loadable child proxy class instance. Due to the use of magic methods`__get()` and `__isset()` methods in the `LazyLoadingProxy` class and some wrong assumptions of the Symfony PropertyAccessor simply null has been retrieved even if the concrete class could not been retrieved (property on a null value instead of an object). The property accessor is used under the hood within the Extbase internal ObjectAccess implementation. The Symfony Team recently declared that behaviour a bug and fixed it with releases `7.0.6` and `6.4.6` and now correctly throwing the `PropertyNotAccessibleException`. Failing nightlies with Symfony releases containing the bugfix revealed a incorrect test implementation, using a constructed and unrealistic construct. This change modifies the test to use a correct access on the LazyLoadingProxy without changing the scenario of the test. [1] https://github.com/symfony/symfony/releases/tag/v7.0.6 [2] https://github.com/symfony/symfony/releases/tag/v6.4.6 [3] symfony/symfony#54194 Resolves: #103531 Related: #101400 Releases: main, 12.4 Change-Id: I5bdd52955af138c1e99b4492c9b5a43839c743cf Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83645 Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Tested-by: Oliver Klee <typo3-coding@oliverklee.de> Tested-by: core-ci <typo3@b13.com> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Reviewed-by: Torben Hansen <derhansen@gmail.com> Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de> Reviewed-by: Stefan Bürk <stefan@buerk.tech> Tested-by: Torben Hansen <derhansen@gmail.com> Tested-by: Stefan Bürk <stefan@buerk.tech>
To harden the Extbase LazyLoadingProxy implementation a new test has been added with #101400, which creates a proxy directly and using ObjectAccess::getProperty() to access a property of the not loadable child proxy class instance. Due to the use of magic methods`__get()` and `__isset()` methods in the `LazyLoadingProxy` class and some wrong assumptions of the Symfony PropertyAccessor simply null has been retrieved even if the concrete class could not been retrieved (property on a null value instead of an object). The property accessor is used under the hood within the Extbase internal ObjectAccess implementation. The Symfony Team recently declared that behaviour a bug and fixed it with releases `7.0.6` and `6.4.6` and now correctly throwing the `PropertyNotAccessibleException`. Failing nightlies with Symfony releases containing the bugfix revealed a incorrect test implementation, using a constructed and unrealistic construct. This change modifies the test to use a correct access on the LazyLoadingProxy without changing the scenario of the test. [1] https://github.com/symfony/symfony/releases/tag/v7.0.6 [2] https://github.com/symfony/symfony/releases/tag/v6.4.6 [3] symfony/symfony#54194 Resolves: #103531 Related: #101400 Releases: main, 12.4 Change-Id: I5bdd52955af138c1e99b4492c9b5a43839c743cf Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83658 Reviewed-by: Stefan Bürk <stefan@buerk.tech> Tested-by: core-ci <typo3@b13.com> Tested-by: Stefan Bürk <stefan@buerk.tech>
To harden the Extbase LazyLoadingProxy implementation a new test has been added with #101400, which creates a proxy directly and using ObjectAccess::getProperty() to access a property of the not loadable child proxy class instance. Due to the use of magic methods`__get()` and `__isset()` methods in the `LazyLoadingProxy` class and some wrong assumptions of the Symfony PropertyAccessor simply null has been retrieved even if the concrete class could not been retrieved (property on a null value instead of an object). The property accessor is used under the hood within the Extbase internal ObjectAccess implementation. The Symfony Team recently declared that behaviour a bug and fixed it with releases `7.0.6` and `6.4.6` and now correctly throwing the `PropertyNotAccessibleException`. Failing nightlies with Symfony releases containing the bugfix revealed a incorrect test implementation, using a constructed and unrealistic construct. This change modifies the test to use a correct access on the LazyLoadingProxy without changing the scenario of the test. [1] https://github.com/symfony/symfony/releases/tag/v7.0.6 [2] https://github.com/symfony/symfony/releases/tag/v6.4.6 [3] symfony/symfony#54194 Resolves: #103531 Related: #101400 Releases: main, 12.4 Change-Id: I5bdd52955af138c1e99b4492c9b5a43839c743cf Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83645 Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Tested-by: Oliver Klee <typo3-coding@oliverklee.de> Tested-by: core-ci <typo3@b13.com> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Reviewed-by: Torben Hansen <derhansen@gmail.com> Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de> Reviewed-by: Stefan Bürk <stefan@buerk.tech> Tested-by: Torben Hansen <derhansen@gmail.com> Tested-by: Stefan Bürk <stefan@buerk.tech>
To harden the Extbase LazyLoadingProxy implementation a new test has been added with #101400, which creates a proxy directly and using ObjectAccess::getProperty() to access a property of the not loadable child proxy class instance. Due to the use of magic methods`__get()` and `__isset()` methods in the `LazyLoadingProxy` class and some wrong assumptions of the Symfony PropertyAccessor simply null has been retrieved even if the concrete class could not been retrieved (property on a null value instead of an object). The property accessor is used under the hood within the Extbase internal ObjectAccess implementation. The Symfony Team recently declared that behaviour a bug and fixed it with releases `7.0.6` and `6.4.6` and now correctly throwing the `PropertyNotAccessibleException`. Failing nightlies with Symfony releases containing the bugfix revealed a incorrect test implementation, using a constructed and unrealistic construct. This change modifies the test to use a correct access on the LazyLoadingProxy without changing the scenario of the test. [1] https://github.com/symfony/symfony/releases/tag/v7.0.6 [2] https://github.com/symfony/symfony/releases/tag/v6.4.6 [3] symfony/symfony#54194 Resolves: #103531 Related: #101400 Releases: main, 12.4 Change-Id: I5bdd52955af138c1e99b4492c9b5a43839c743cf Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83658 Reviewed-by: Stefan Bürk <stefan@buerk.tech> Tested-by: core-ci <typo3@b13.com> Tested-by: Stefan Bürk <stefan@buerk.tech>
I guess that a better sollution will be to create an interface for classes that will ckeck existance of magic properties, e.g. MagicPropertyExistanceExtractorInterface, and if Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor implements this interface delegate the existance check to it. It will allow to implement application depended logic related to magic properties without workarounds. |
This change broke my tests. They work with 6.4.4 and not with 6.4.6. I use magic getters in one of my entities like so: public function __get(string $arg)
{
if (preg_match('/custom_checkbox_(\d+)_entry(_other)?/', $arg, $matches)) {
if (isset($matches[2])) {
return $this->getCustomCheckboxEntryOther((int) $matches[1]);
}
return $this->getCustomCheckboxEntryForCheckbox((int) $matches[1]);
}
if (preg_match('/customCheckboxEntryValueByCheckboxId(\d+)/', $arg, $matches)) {
return $this->getCustomCheckboxEntryValueByCheckboxId((int) $matches[1]);
}
} my tests use |
@craigh you might have a broken implementation of |
@nicolas-grekas of course, you are correct 🎉 thank you for your keen insight and quick response! |
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38013) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
This is a BC break, I'm now getting:
Even if I have this, to access dynamic properties stored in a json column:
It's look like the magic getter is never called |
@fmonts same as above: you likely have a broken implementation of __isset, please have a look and try to fix it. |
I don't have any
to many entities... |
That's why then. You relied on a specific behavior of PropertyAccess, which is broken in the generic case (eg the |
This seems to break access to properties in Laravel Eloquent models when the value is I'm not sure if there is a 'standard' way to check for access there, because of the way ActiveRecord works (at least in Laravel). In Laravel it is always possible to set or get a property on the model.. |
…ess v6.4.6 (#38014) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38014) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38014) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38014) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38014) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38014) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
…ess v6.4.6 (#38014) - since symfony/property-access 6.4.6 the application crashed with a lot of exceptions like "Can't get a way to read the property ... in class ...", see symfony/symfony#54194
PropertyAccess and PropertyInfo make a few assumptions when magic methods are involved.
Namely they assume that if a
__get
method is defined, then any property name is accessible.This assumption is generally wrong, and this becomes more evident with the introduction of lazy objects.
The linked issue gives some more details.
In this PR, I tweak these assumptions in order to make less of them.
Note that there is no bullet-proof way to decide if a virtual property exists in PHP. We're missing an
__exists()
magic method for that. Because of this, I'm submitting this PR to 6.4 and not 5.4. Let 5.4 end its life quietly and ensure 6.4 works at its best with lazy ghosts, where they're mainstream.