Bug #92357

Extbase / Symfony: Domain Object Validation with Lazy Loading ignores Getters

Added by Till Wimmer about 1 year ago. Updated 6 months ago.

Status:
Accepted
Priority:
Should have
Assignee:
-
Category:
Extbase
Target version:
-
Start date:
2020-09-21
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
10
PHP Version:
7.4
Tags:
extbase symfony validation lazyloading
Complexity:
Is Regression:
Sprint Focus:

Description

There is an issue with model validation in V10 when lazy loading is involved.

In such a case we get the PHP error:

Cannot access protected property Myvend\Myext\Domain\Model\Myclass::$property

I.e. it tries to access the (protected) property instead of using the getter.

The reason is that Symfony analyzes the LazyLoadingProxy object instead of the real class and then gets the ACCESS_TYPE_PROPERTY (/var/www/typo3_src-10.4.8/vendor/symfony/property-access/PropertyAccessor.php line 398):

                    throw $e;
                }
            } elseif (self::ACCESS_TYPE_PROPERTY === $access[self::ACCESS_TYPE]) {
                $result[self::VALUE] = $object->{$access[self::ACCESS_NAME]};

                if ($access[self::ACCESS_REF] && isset($zval[self::REF])) {
                    $result[self::REF] = &$object->{$access[self::ACCESS_NAME]};
                }

This happens in Symfony\Component\PropertyAccess::readProperty() by calling getReadAccessInfo().

My workaround is adding those lines starting at 377, readProperty():

    private function readProperty(array $zval, string $property, bool $ignoreInvalidProperty = false): array
    {
        if (!\is_object($zval[self::VALUE])) {
            throw new NoSuchPropertyException(sprintf('Cannot read property "%s" from an array. Maybe you intended to write the property path as "[%1$s]" instead.', $property));
        }

377:    if ($zval[self::VALUE] instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) {
378:        $zval[self::VALUE] = $zval[self::VALUE]->_loadRealInstance();
379:    }
#1

Updated by Till Wimmer about 1 year ago

  • Subject changed from Extbase / Symfony: Domain Object Validation with Lazy Lodaing ignores Getters to Extbase / Symfony: Domain Object Validation with Lazy Loading ignores Getters
#2

Updated by Till Wimmer about 1 year ago

Two hours later:

The fix should rather go to /extbase/Classes/Validation/Validator/GenericObjectValidator.php:

    protected function getPropertyValue($object, $propertyName)
    {
        // @todo add support for lazy loading proxies, if needed
        if (ObjectAccess::isPropertyGettable($object, $propertyName)) {
            return ObjectAccess::getProperty($object, $propertyName);
        }
        throw new \RuntimeException(
            sprintf(
                'Could not get value of property "%s::%s", make sure the property is either public or has a getter get%3$s(), a hasser has%3$s() or an isser is%3$s().',
                get_class($object),
                $propertyName,
                ucfirst($propertyName)
            ),
            1546632293
        );
    }
#3

Updated by Simon Schaufelberger 10 months ago

I'm having the exact same bug and I'm totally stuck as I have a lazy dependency to static_countries and extbase tries to validate $countryZones in the Country model which will crash because of this.

How to reproduce:

Create a model A with a lazy dependency $country to static_countries and validate model A.

Workaround: make all affected properties public.

#4

Updated by Xavier Perseguers 6 months ago

  • Status changed from New to Accepted

Confirmed.

Also available in: Atom PDF