Skip to content

Commit

Permalink
Don't rely on LazyProxyTrait in LazyServiceEntityRepository
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Nov 13, 2023
1 parent ca64ca7 commit 31e14d1
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 107 deletions.
75 changes: 52 additions & 23 deletions Repository/LazyServiceEntityRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use LogicException;
use Symfony\Component\VarExporter\LazyGhostTrait;
use Symfony\Component\VarExporter\LazyObjectInterface;

use function debug_backtrace;
use function sprintf;

use const DEBUG_BACKTRACE_IGNORE_ARGS;

/**
* @internal Extend {@see ServiceEntityRepository} instead.
*
Expand All @@ -18,41 +20,68 @@
*/
class LazyServiceEntityRepository extends EntityRepository implements ServiceEntityRepositoryInterface
{
use LazyGhostTrait {
createLazyGhost as private;
}
private ManagerRegistry $registry;
private string $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)
{
$initializer = function ($instance, $property) use ($registry, $entityClass) {
$manager = $registry->getManagerForClass($entityClass);
$this->registry = $registry;
$this->entityClass = $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 ($this instanceof LazyObjectInterface) {
$this->initialize();

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

Check warning on line 38 in Repository/LazyServiceEntityRepository.php

View check run for this annotation

Codecov / codecov/patch

Repository/LazyServiceEntityRepository.php#L38

Added line #L38 was not covered by tests
}

return $this->$property;
};
unset($this->_em);
unset($this->_class);
unset($this->_entityName);
}

if ($this instanceof LazyObjectInterface) {
$initializer($this, '_entityName');
/**
* @param string|int $name
*
* @return mixed
*/
public function __get($name)
{
$this->initialize();

return;
$scope = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['class'] ?? null;

return (function () use ($name) {
return $this->$name;
})->bindTo($this, $scope)();
}

/** @param string|int $name */
public function __isset($name): bool

Check warning on line 63 in Repository/LazyServiceEntityRepository.php

View check run for this annotation

Codecov / codecov/patch

Repository/LazyServiceEntityRepository.php#L63

Added line #L63 was not covered by tests
{
$this->initialize();

Check warning on line 65 in Repository/LazyServiceEntityRepository.php

View check run for this annotation

Codecov / codecov/patch

Repository/LazyServiceEntityRepository.php#L65

Added line #L65 was not covered by tests

$scope = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['class'] ?? null;

Check warning on line 67 in Repository/LazyServiceEntityRepository.php

View check run for this annotation

Codecov / codecov/patch

Repository/LazyServiceEntityRepository.php#L67

Added line #L67 was not covered by tests

return (function () use ($name) {
return isset($this->$name);
})->bindTo($this, $scope)();

Check warning on line 71 in Repository/LazyServiceEntityRepository.php

View check run for this annotation

Codecov / codecov/patch

Repository/LazyServiceEntityRepository.php#L69-L71

Added lines #L69 - L71 were not covered by tests
}

private function initialize(): void
{
$manager = $this->registry->getManagerForClass($this->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.',
$this->entityClass,
));
}

self::createLazyGhost([
"\0*\0_em" => $initializer,
"\0*\0_class" => $initializer,
"\0*\0_entityName" => $initializer,
], null, $this);
parent::__construct($manager, $manager->getClassMetadata($this->entityClass));
}
}
38 changes: 0 additions & 38 deletions Repository/LegacyServiceEntityRepository.php

This file was deleted.

66 changes: 20 additions & 46 deletions Repository/ServiceEntityRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,30 @@
namespace Doctrine\Bundle\DoctrineBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\VarExporter\LazyGhostTrait;

use function property_exists;
use function trait_exists;

if (property_exists(EntityRepository::class, '_entityName')) {
if (trait_exists(LazyGhostTrait::class)) {
// ORM 2 with VarExporter
/**
* 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 LazyServiceEntityRepository<T>
*/
class ServiceEntityRepository extends LazyServiceEntityRepository
{
}
} else {
// ORM 2 without VarExporter
/**
* 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 LegacyServiceEntityRepository<T>
*/
class ServiceEntityRepository extends LegacyServiceEntityRepository
{
}
// ORM 2
/**
* 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 LazyServiceEntityRepository<T>
*/
class ServiceEntityRepository extends LazyServiceEntityRepository
{
}
} else {
// ORM 3
Expand Down

0 comments on commit 31e14d1

Please sign in to comment.