Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Serializer] Fix unitialized properties (from PHP 7.4.2) when serializing context for the cache key#36332

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

@alanpoulain
Copy link
Contributor

@alanpoulainalanpoulain commentedApr 3, 2020
edited
Loading

QA
Branch?3.4
Bug fix?yes
New feature?no
Deprecations?no
TicketsFix#35574doctrine/orm#8030
LicenseMIT
Doc PRN/A

This bug only happens on the following conditions:

  • A Doctrine entity (Book) having a relation with another entity (Author) is used;
  • TheAuthor entity uses typed properties (PHP 7.4) not initialized;
  • TheSerializer is used with theBook in theOBJECT_TO_POPULATE key in the context.

For instance:

<?phpdeclare(strict_types=1);namespaceApp\Entity;useDoctrine\ORM\MappingasORM;/** @ORM\Entity */class Book{/**     * @ORM\ManyToOne(targetEntity="Author")     */publicAuthor$author;public ?string$isbn;}
<?phpdeclare(strict_types=1);namespaceApp\Entity;useDoctrine\ORM\MappingasORM;/** @ORM\Entity */class Author{public ?string$name;}

Or even:

<?phpdeclare(strict_types=1);namespaceApp\Entity;useDoctrine\ORM\MappingasORM;/** @ORM\Entity */class Author{privatestring$name;publicfunction__construct()    {$this->name ='Leo';    }}

If the following is done (it's the case for instance in API Platform when aPUT is made):

$serializer->deserialize('{"isbn":"2038717141"}', Book::class,'json', ['object_to_populate' =>$book]);

Then there will be the following error:

Fatal error: Typed property Proxies_CG_\App\Entity\Author::$ must not be accessed before initialization (in __sleep)

It's because of these lines in thegetCacheKey method of theAbstractObjectNormalizer:

returnmd5($format.serialize([
'context' =>$context,
'ignored' =>$this->ignoredAttributes,
'camelized' =>$this->camelizedAttributes,
]));

Since the lazy proxyfied relation has a__sleep with unitialized properties, theserialize method will throw (sincehttps://bugs.php.net/bug.php?id=79002:php/php-src@846b647).

I propose to fix this issue by unsetting theOBJECT_TO_POPULATE key in the context because I don't think it's useful for determining the attributes of the object.

For the next versions of Symfony, the fix should probably be elsewhere, in the default context.
For instance in Symfony 4.4, instead of:

$this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] = [self::CIRCULAR_REFERENCE_LIMIT_COUNTERS];

It should be:

$this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] = [self::CIRCULAR_REFERENCE_LIMIT_COUNTERS,self::OBJECT_TO_POPULATE];

But I'm not sure how it should be merged (another PR maybe?).

@dunglas
Copy link
Member

dunglas commentedApr 3, 2020
edited
Loading

To be honest, I'm not sure if what you describe in the description is a bug or not, because when using typed properties, you must always initialize the property, either in its definition of in the constructor, that's the spirit of this feature. However, your patch is legit, because according to the Doctrine documentation:

If you intend to serialize (and unserialize) entity instances that still hold references to proxy objects you may run into problems with private properties because of technical limitations. Proxy objects implement __sleep and it is not possible for __sleep to return names of private properties in parent classes.

object_to_populate likely contains a Doctrine entity, so we must not serialize it (+ it's useless to serialize it).

Could you add a test to prevent regressions? (Just testing than putting something to serializable such as a closure inobject_to_populate will be enough, no need for a Doctrine entity).

@dunglas
Copy link
Member

Also, there is probably something to fix in Doctrine too. Our call toserialize() is already in a try/catch block. Doctrine shouldn't generate uncatchable errors like that.

@alanpoulain
Copy link
ContributorAuthor

It cannot really tested since serializing a closure will throw an exception, not an error (and the exception is catched).
And there is already a test inObjectNormalizerTest to test this behavior (testNormalizeNotSerializableContext).

@2ec0b4
Copy link

Pay attention to the destination branch: symfony:3.4 here, but the initial issue#35574 is about symfony:4.4. This should be applied on several versions?

I reproduce this behavior on SF 4.4 here:doctrine/common#886 (comment)

@dunglas
Copy link
Member

@alanpoulain for the test you can do the like it that:https://github.com/symfony/symfony/pull/36336/files#diff-e6bd6c603753788029968840196a888cR395

@2ec0b4 patches are merged to upper branches, it will be fixed in 3.4 and all superior versions.

alanpoulain, 2ec0b4, and bizley reacted with thumbs up emoji

@nicolas-grekasnicolas-grekas added this to the3.4 milestoneApr 3, 2020
@fabpotfabpotforce-pushed theserializer-fix-cache-key-unitialized-properties branch from03bd90a to1fafff7CompareApril 4, 2020 07:17
@fabpot
Copy link
Member

Thank you@alanpoulain.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@fabpotfabpotfabpot approved these changes

@dunglasdunglasdunglas approved these changes

@chalasrchalasrchalasr approved these changes

Assignees

No one assigned

Projects

None yet

Milestone

3.4

Development

Successfully merging this pull request may close these issues.

7 participants

@alanpoulain@dunglas@2ec0b4@fabpot@chalasr@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp