Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ return function (ClassMetadata $metadata): void {
};
```

## Do not pass any proxy interface to `AbstractManagerRegistry` when using native proxies

With PHP 8.4 native lazy objects, you don't need to pass any proxy interface to
`AbstractManagerRegistry`. The class of the lazy objects is the class being mapped.

# Upgrade to 4.0

## BC Break: Removed `StaticReflectionService`
Expand Down
26 changes: 14 additions & 12 deletions src/AbstractManagerRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ abstract class AbstractManagerRegistry implements ManagerRegistry
/**
* @param array<string, string> $connections
* @param array<string, string> $managers
* @phpstan-param class-string $proxyInterfaceName
* @phpstan-param class-string|null $proxyInterfaceName Set to null when native lazy objects are used.
*/
public function __construct(
private readonly string $name,
private array $connections,
private array $managers,
private readonly string $defaultConnection,
private readonly string $defaultManager,
private readonly string $proxyInterfaceName,
private readonly string|null $proxyInterfaceName = null,
) {
}

Expand Down Expand Up @@ -127,19 +127,21 @@ public function getManager(string|null $name = null): ObjectManager

public function getManagerForClass(string $class): ObjectManager|null
{
$proxyClass = new ReflectionClass($class);
if ($proxyClass->isAnonymous()) {
return null;
}

if ($proxyClass->implementsInterface($this->proxyInterfaceName)) {
$parentClass = $proxyClass->getParentClass();

if ($parentClass === false) {
if ($this->proxyInterfaceName !== null) {
$proxyClass = new ReflectionClass($class);
if ($proxyClass->isAnonymous()) {
return null;
}

$class = $parentClass->getName();
if ($proxyClass->implementsInterface($this->proxyInterfaceName)) {
$parentClass = $proxyClass->getParentClass();

if ($parentClass === false) {
return null;
}

$class = $parentClass->getName();
}
}

foreach ($this->managers as $id) {
Expand Down
53 changes: 51 additions & 2 deletions tests/ManagerRegistryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ public function testGetManagerForClass(): void
);
}

public function testGetManagerForClassAnonymous(): void
{
$anonymousClass = new class extends TestObject implements Proxy {
public function __isInitialized(): bool
{
return true;
}

public function __load(): void
{
}
};

self::assertNull($this->mr->getManagerForClass($anonymousClass::class));
}

public function testGetManagerForProxiedClass(): void
{
self::assertInstanceOf(
Expand All @@ -64,6 +80,39 @@ public function testGetManagerForAnonymousClass(): void
})::class));
}

public function testGetManagerForWithoutProxyInterface(): void
{
$mr = new TestManagerRegistry(
'ORM',
['default' => 'default_connection'],
['default' => 'default_manager'],
'default',
'default',
null,
$this->getManagerFactory(),
);

self::assertInstanceOf(
ObjectManager::class,
$mr->getManagerForClass(TestObject::class),
);

self::assertNull($mr->getManagerForClass(TestObjectProxy::class));

$anonymousClass = new class extends TestObject implements Proxy {
public function __isInitialized(): bool
{
return true;
}

public function __load(): void
{
}
};

self::assertNull($mr->getManagerForClass($anonymousClass::class));
}

public function testResetManager(): void
{
$manager = $this->mr->getManager();
Expand Down Expand Up @@ -179,15 +228,15 @@ class TestManagerRegistry extends AbstractManagerRegistry
/**
* {@inheritDoc}
*
* @phpstan-param class-string $proxyInterfaceName
* @phpstan-param class-string|null $proxyInterfaceName
*/
public function __construct(
string $name,
array $connections,
array $managers,
string $defaultConnection,
string $defaultManager,
string $proxyInterfaceName,
string|null $proxyInterfaceName,
callable $managerFactory,
) {
$this->managerFactory = $managerFactory;
Expand Down