IBX-11179: Resolve PHP 8.4 lazy proxy incompatibility#707
IBX-11179: Resolve PHP 8.4 lazy proxy incompatibility#707
Conversation
279fbba to
856bb49
Compare
2e7d02f to
ba89981
Compare
phpstan-baseline.neon
Outdated
| path: src/lib/Persistence/Cache/UserPreferenceHandler.php | ||
|
|
||
| - | ||
| message: '#^Return type \(Doctrine\\ORM\\Mapping\\ClassMetadataFactory\) of method Ibexa\\Core\\Persistence\\Doctrine\\SiteAccessAwareEntityManager\:\:getMetadataFactory\(\) should be compatible with return type \(Doctrine\\Persistence\\Mapping\\ClassMetadataFactory\<Doctrine\\Persistence\\Mapping\\ClassMetadata\<object\>\>\) of method Doctrine\\Persistence\\ObjectManager\:\:getMetadataFactory\(\)$#' |
There was a problem hiding this comment.
We don't add new entries to PHPStan baseline in the new code, please resolve this one as well.
There was a problem hiding this comment.
@konradoboza
The problem is that :
\Doctrine\ORM\EntityManagerInterface has:
/**
* EntityManager interface
*
* @method Mapping\ClassMetadataFactory getMetadataFactory()
* @method mixed wrapInTransaction(callable $func)
* @method void refresh(object $object, ?int $lockMode = null)
*/
interface EntityManagerInterface extends ObjectManager
and in: \Doctrine\Persistence\ObjectManager
there is :
/**
* Gets the metadata factory used to gather the metadata of classes.
*
* @phpstan-return ClassMetadataFactory<ClassMetadata<object>>
*/
public function getMetadataFactory();
Should I add phpstan line ignore to SiteAccessAwareEntityManager instead of adding it to phpstan-baseline ?
| class: Doctrine\ORM\EntityManager | ||
| lazy: true | ||
| factory: ['@ibexa.doctrine.orm.entity_manager_factory', 'getEntityManager'] | ||
| class: Ibexa\Core\Persistence\Doctrine\SiteAccessAwareEntityManager |
There was a problem hiding this comment.
Should we also have decorates: here?
Regardless: doesn't that approach leave us with some technical debt we need to reassess later while upgrading dependencies late? I wonder how Doctrine themselves have dealt with providing support for PHP8.4. Have you checked that? First idea is the one we initially have - bumping the dependency version. However, maybe there is a specific PHP8.4-compatibility-related part we might be able to utilize for the time being.
There was a problem hiding this comment.
It should NOT decorate the primary Doctrine Entity Manager.
We only expect it to "overwrite" the default behavior specifically when we ask for ibexa.doctrine.orm.entity_manager service.
…d improve PHP 8.4 compatibility
ba89981 to
d6345e6
Compare
| private function getWrapped(): EntityManagerInterface | ||
| { | ||
| return $this->resolvedEntityManager ??= $this->entityManagerFactory->getEntityManager(); | ||
| } |
There was a problem hiding this comment.
As we discussed on daily meetup, I expect this $this->resolvedEntityManager to be reset when SiteAccess changes (Ibexa\Core\MVC\Symfony\MVCEvents::CONFIG_SCOPE_CHANGE or Ibexa\Core\MVC\Symfony\MVCEvents::CONFIG_SCOPE_RESTORE).
Additionally, up for debate within team, is whether we should use kernel.reset, since we have effectively a stateful service.
9b243f1 to
3b865c7
Compare
|



Description:
This pull request removes the lazy loading mechanism from Doctrine EntityManager to ensure full PHP 8.4 compatibility. The issue arises from Symfony's lazy proxy factory limitation when handling nested lazy services, which is incompatible with PHP 8.4's strict lazy proxy requirements.
PHP 8.4 introduces stricter rules for lazy proxy handling. Symfony's lazy proxy factory cannot handle nested lazy services, resulting in the error: "Lazy proxy factory must return a non-lazy object". The current implementation of EntityManager relied on lazy loading, which violates this constraint.
The fix implements
SiteAccessAwareEntityManager, a non-lazy decorator that wrapsEntityManagerand implements explicit lazy resolution viaEntityManagerFactory.(almost) green regressions : ibexa/commerce#1668
Results discussed with QA and these fails are known.
For QA:
Please do sanities with multirepository setup
Documentation: