Skip to content

Commit

Permalink
Make ServiceEntityRepository lazy on Symfony 6.2+
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Dec 30, 2022
1 parent 0421ebc commit c31d200
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 30 deletions.
62 changes: 62 additions & 0 deletions Repository/LazyServiceEntityRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Doctrine\Bundle\DoctrineBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use LogicException;
use Symfony\Component\VarExporter\LazyGhostTrait;

use function sprintf;

/**
* Optional EntityRepository base class with a simplified constructor (for autowiring).
*
* To use in your class, inject the "registry" service and call
* the parent constructor. For example:
*
* class YourEntityRepository extends ServiceEntityRepository
* {
* public function __construct(ManagerRegistry $registry)
* {
* parent::__construct($registry, YourEntity::class);
* }
* }
*
* @internal to be renamed ServiceEntityRepository when PHP 8.1 / Symfony 6.2 becomes required
*
* @template T of object
* @template-extends EntityRepository<T>
*/
class LazyServiceEntityRepository extends EntityRepository implements ServiceEntityRepositoryInterface
{
use LazyGhostTrait;

/**
* @param string $entityClass The class name of the entity this repository manages
* @psalm-param class-string<T> $entityClass
*/
public function __construct(ManagerRegistry $registry, string $entityClass)
{
$initializer = function ($instance, $property) use ($registry, $entityClass) {
$manager = $registry->getManagerForClass($entityClass);

if ($manager === null) {
throw new LogicException(sprintf(
'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata.',
$entityClass
));
}

parent::__construct($manager, $manager->getClassMetadata($entityClass));

return $this->$property;
};

self::createLazyGhost([
"\0*\0_em" => $initializer,
"\0*\0_class" => $initializer,
"\0*\0_entityName" => $initializer,
], null, $this);
}
}
67 changes: 37 additions & 30 deletions Repository/ServiceEntityRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,50 @@
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use LogicException;
use Symfony\Component\VarExporter\LazyGhostTrait;

use function class_alias;
use function sprintf;
use function trait_exists;

/**
* Optional EntityRepository base class with a simplified constructor (for autowiring).
*
* To use in your class, inject the "registry" service and call
* the parent constructor. For example:
*
* class YourEntityRepository extends ServiceEntityRepository
* {
* public function __construct(ManagerRegistry $registry)
* {
* parent::__construct($registry, YourEntity::class);
* }
* }
*
* @template T of object
* @template-extends EntityRepository<T>
*/
class ServiceEntityRepository extends EntityRepository implements ServiceEntityRepositoryInterface
{
if (trait_exists(LazyGhostTrait::class)) {
class_alias(LazyServiceEntityRepository::class, ServiceEntityRepository::class);
} else {
/**
* @param string $entityClass The class name of the entity this repository manages
* @psalm-param class-string<T> $entityClass
* Optional EntityRepository base class with a simplified constructor (for autowiring).
*
* To use in your class, inject the "registry" service and call
* the parent constructor. For example:
*
* class YourEntityRepository extends ServiceEntityRepository
* {
* public function __construct(ManagerRegistry $registry)
* {
* parent::__construct($registry, YourEntity::class);
* }
* }
*
* @template T of object
* @template-extends EntityRepository<T>
*/
public function __construct(ManagerRegistry $registry, string $entityClass)
class ServiceEntityRepository extends EntityRepository implements ServiceEntityRepositoryInterface
{
$manager = $registry->getManagerForClass($entityClass);
/**
* @param string $entityClass The class name of the entity this repository manages
* @psalm-param class-string<T> $entityClass
*/
public function __construct(ManagerRegistry $registry, string $entityClass)
{
$manager = $registry->getManagerForClass($entityClass);

if ($manager === null) {
throw new LogicException(sprintf(
'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata.',
$entityClass
));
}
if ($manager === null) {
throw new LogicException(sprintf(
'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata.',
$entityClass
));
}

parent::__construct($manager, $manager->getClassMetadata($entityClass));
parent::__construct($manager, $manager->getClassMetadata($entityClass));
}
}
}
5 changes: 5 additions & 0 deletions psalm.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
<referencedClass name="Symfony\Component\VarExporter\LazyObjectInterface"/>
</errorLevel>
</UndefinedClass>
<UndefinedTrait>
<errorLevel type="suppress">
<referencedClass name="Symfony\Component\VarExporter\LazyGhostTrait"/>
</errorLevel>
</UndefinedTrait>
<UndefinedDocblockClass>
<errorLevel type="suppress">
<!-- https://github.com/symfony/symfony/issues/45609 -->
Expand Down

0 comments on commit c31d200

Please sign in to comment.