doctrine / doctrine/persistence

Object that are not entities are checked for Metadata without cache

Open
#96 1 comment 4 reactions 0 assignees View on GitHub
Dominant language
PHP
Stars
4k
Forks
76
Avg merge
3d 20h
Merged PRs (30d)
2

Description

This is a followup of https://github.com/doctrine/dbal/issues/3838, I just want to check if maintainers see a room for improvement.

TL;DR: when we check metadata for doctrine entities, there is a cache that prevents checking for metadata across requests and there is memoization to prevent hitting on the cache. When passing objects that are not doctrine entities [with fallback](https://github.com/doctrine/orm/blob/e77091399a4475630a833fc33bff0d54c194511a/lib/Doctrine/ORM/AbstractQuery.php#L344-L346) there is no cache but memoization, and without fallback there is none of that.

There are at least two paths that trigger that behavior (just to show that this is not an easy fix in userland):

1/ doctrine query with datetime parameter without the third parameter "datetime" (dev and prod)

```php
$q = $em->createQuery('SELECT d from App\Entity\DataSample d WHERE d.referenceDate = :date');
$q->setParameter('date', Carbon::now(), 'datetime');
```

- https://github.com/doctrine/orm/blob/e77091399a4475630a833fc33bff0d54c194511a/lib/Doctrine/ORM/AbstractQuery.php#L402
- https://github.com/doctrine/orm/blob/e77091399a4475630a833fc33bff0d54c194511a/lib/Doctrine/ORM/UnitOfWork.php#L2491
- https://github.com/doctrine/orm/blob/e77091399a4475630a833fc33bff0d54c194511a/lib/Doctrine/ORM/EntityManager.php#L286
- https://github.com/doctrine/persistence/blob/fdaaa50cb23760c9da2d6dcab9f10caa34d92b61/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php#L161
- https://github.com/doctrine/persistence/blob/fdaaa50cb23760c9da2d6dcab9f10caa34d92b61/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php#L206

This is fixable in userland, but quite not fun.

This is a blackfire profile in prod env with 20 sql requests with a datetime parameter WITHOUT the third parameter set. The after is a simple test at the beginning of the getMetadataFor to avoid loading the metadata stack:

```php
if ($className === 'DateTime') {
throw new MappingException();
}
```
![image](https://user-images.githubusercontent.com/84887/74433507-cf4d5480-4e60-11ea-975f-e3747063bc40.png)

2/ symfony validation (dev only)

- https://github.com/symfony/symfony/blob/4c1ca329a440fbf98ac90208a79292606d4cd92c/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php#L101
- https://github.com/symfony/symfony/blob/4c1ca329a440fbf98ac90208a79292606d4cd92c/src/Symfony/Component/Validator/Mapping/Loader/LoaderChain.php#L54
- https://github.com/symfony/symfony/blob/4c1ca329a440fbf98ac90208a79292606d4cd92c/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php#L51
- https://github.com/doctrine/orm/blob/e77091399a4475630a833fc33bff0d54c194511a/lib/Doctrine/ORM/EntityManager.php#L286
- https://github.com/doctrine/persistence/blob/fdaaa50cb23760c9da2d6dcab9f10caa34d92b61/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php#L161
- https://github.com/doctrine/persistence/blob/fdaaa50cb23760c9da2d6dcab9f10caa34d92b61/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php#L206

3/ doctrine embedable classes

----

I don't know the best fix for that but I figures that on the life on a request / cache, this should not happen. Even I who know this bug, I forgot to add the third parameter, it should really be resolved in doctrine/persistence.

We could:
- cache the exception and add some instanceof / throw somewhere.
- cache null and return an exception if null, we should change the isset by array_key_exists

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.