[DoctrineBridge] Deprecate auto-mapping of entities in favor of mapped route parameters

This commit is contained in:
Nicolas Grekas
2024-04-02 11:43:50 +02:00
parent e0d1f2d113
commit 1810cac33f
5 changed files with 55 additions and 50 deletions

View File

@@ -60,7 +60,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
if ($attribute->disabled) {
$disabledResolvers[$attribute->resolver] = true;
} elseif ($resolverName) {
throw new \LogicException(sprintf('You can only pin one resolver per argument, but argument "$%s" of "%s()" has more.', $metadata->getName(), $this->getPrettyName($controller)));
throw new \LogicException(sprintf('You can only pin one resolver per argument, but argument "$%s" of "%s()" has more.', $metadata->getName(), $metadata->getControllerName()));
} else {
$resolverName = $attribute->resolver;
}
@@ -118,7 +118,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
}
}
throw new \RuntimeException(sprintf('Controller "%s" requires the "$%s" argument that could not be resolved. '.($reasonCounter > 1 ? 'Possible reasons: ' : '').'%s', $this->getPrettyName($controller), $metadata->getName(), implode(' ', $reasons)));
throw new \RuntimeException(sprintf('Controller "%s" requires the "$%s" argument that could not be resolved. '.($reasonCounter > 1 ? 'Possible reasons: ' : '').'%s', $metadata->getControllerName(), $metadata->getName(), implode(' ', $reasons)));
}
return $arguments;
@@ -137,21 +137,4 @@ final class ArgumentResolver implements ArgumentResolverInterface
new VariadicValueResolver(),
];
}
private function getPrettyName($controller): string
{
if (\is_array($controller)) {
if (\is_object($controller[0])) {
$controller[0] = get_debug_type($controller[0]);
}
return $controller[0].'::'.$controller[1];
}
if (\is_object($controller)) {
return get_debug_type($controller);
}
return $controller;
}
}

View File

@@ -31,6 +31,7 @@ class ArgumentMetadata
private mixed $defaultValue,
private bool $isNullable = false,
private array $attributes = [],
private string $controllerName = 'n/a',
) {
$this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue);
}
@@ -135,4 +136,9 @@ class ArgumentMetadata
return $attributes;
}
public function getControllerName(): string
{
return $this->controllerName;
}
}

View File

@@ -22,6 +22,7 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
{
$arguments = [];
$reflector ??= new \ReflectionFunction($controller(...));
$controllerName = $this->getPrettyName($reflector);
foreach ($reflector->getParameters() as $param) {
$attributes = [];
@@ -31,7 +32,7 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
}
}
$arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull(), $attributes);
$arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull(), $attributes, $controllerName);
}
return $arguments;
@@ -53,4 +54,19 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
default => $name,
};
}
private function getPrettyName(\ReflectionFunctionAbstract $r): string
{
$name = $r->name;
if ($r instanceof \ReflectionMethod) {
return $r->class.'::'.$name;
}
if ($r->isAnonymous() || !$class = $r->getClosureCalledClass()) {
return $name;
}
return $class->name.'::'.$name;
}
}

View File

@@ -184,7 +184,7 @@ class ArgumentResolverTest extends TestCase
$controller = (new ArgumentResolverTestController())->controllerWithFoo(...);
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Controller "Closure" requires the "$foo" argument that could not be resolved. Either the argument is nullable and no null value has been provided, no default value has been provided or there is a non-optional argument after this one.');
$this->expectExceptionMessage('Controller "'.ArgumentResolverTestController::class.'::controllerWithFoo" requires the "$foo" argument that could not be resolved. Either the argument is nullable and no null value has been provided, no default value has been provided or there is a non-optional argument after this one.');
self::getResolver()->getArguments($request, $controller);
}

View File

@@ -32,12 +32,12 @@ class ArgumentMetadataFactoryTest extends TestCase
public function testSignature1()
{
$arguments = $this->factory->createArgumentMetadata($this->signature1(...));
$arguments = $this->factory->createArgumentMetadata([$this, 'signature1']);
$this->assertEquals([
new ArgumentMetadata('foo', self::class, false, false, null),
new ArgumentMetadata('bar', 'array', false, false, null),
new ArgumentMetadata('baz', 'callable', false, false, null),
new ArgumentMetadata('foo', self::class, false, false, null, controllerName: $this::class.'::signature1'),
new ArgumentMetadata('bar', 'array', false, false, null, controllerName: $this::class.'::signature1'),
new ArgumentMetadata('baz', 'callable', false, false, null, controllerName: $this::class.'::signature1'),
], $arguments);
}
@@ -46,9 +46,9 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata($this->signature2(...));
$this->assertEquals([
new ArgumentMetadata('foo', self::class, false, true, null, true),
new ArgumentMetadata('bar', FakeClassThatDoesNotExist::class, false, true, null, true),
new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, true, null, true),
new ArgumentMetadata('foo', self::class, false, true, null, true, controllerName: $this::class.'::signature2'),
new ArgumentMetadata('bar', FakeClassThatDoesNotExist::class, false, true, null, true, controllerName: $this::class.'::signature2'),
new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, true, null, true, controllerName: $this::class.'::signature2'),
], $arguments);
}
@@ -57,8 +57,8 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata($this->signature3(...));
$this->assertEquals([
new ArgumentMetadata('bar', FakeClassThatDoesNotExist::class, false, false, null),
new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, false, null),
new ArgumentMetadata('bar', FakeClassThatDoesNotExist::class, false, false, null, controllerName: $this::class.'::signature3'),
new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, false, null, controllerName: $this::class.'::signature3'),
], $arguments);
}
@@ -67,9 +67,9 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata($this->signature4(...));
$this->assertEquals([
new ArgumentMetadata('foo', null, false, true, 'default'),
new ArgumentMetadata('bar', null, false, true, 500),
new ArgumentMetadata('baz', null, false, true, []),
new ArgumentMetadata('foo', null, false, true, 'default', controllerName: $this::class.'::signature4'),
new ArgumentMetadata('bar', null, false, true, 500, controllerName: $this::class.'::signature4'),
new ArgumentMetadata('baz', null, false, true, [], controllerName: $this::class.'::signature4'),
], $arguments);
}
@@ -78,8 +78,8 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata($this->signature5(...));
$this->assertEquals([
new ArgumentMetadata('foo', 'array', false, true, null, true),
new ArgumentMetadata('bar', null, false, true, null, true),
new ArgumentMetadata('foo', 'array', false, true, null, true, controllerName: $this::class.'::signature5'),
new ArgumentMetadata('bar', null, false, true, null, true, controllerName: $this::class.'::signature5'),
], $arguments);
}
@@ -88,8 +88,8 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata([new VariadicController(), 'action']);
$this->assertEquals([
new ArgumentMetadata('foo', null, false, false, null),
new ArgumentMetadata('bar', null, true, false, null),
new ArgumentMetadata('foo', null, false, false, null, controllerName: VariadicController::class.'::action'),
new ArgumentMetadata('bar', null, true, false, null, controllerName: VariadicController::class.'::action'),
], $arguments);
}
@@ -98,9 +98,9 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata([new BasicTypesController(), 'action']);
$this->assertEquals([
new ArgumentMetadata('foo', 'string', false, false, null),
new ArgumentMetadata('bar', 'int', false, false, null),
new ArgumentMetadata('baz', 'float', false, false, null),
new ArgumentMetadata('foo', 'string', false, false, null, controllerName: BasicTypesController::class.'::action'),
new ArgumentMetadata('bar', 'int', false, false, null, controllerName: BasicTypesController::class.'::action'),
new ArgumentMetadata('baz', 'float', false, false, null, controllerName: BasicTypesController::class.'::action'),
], $arguments);
}
@@ -109,9 +109,9 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata($this->signature1(...));
$this->assertEquals([
new ArgumentMetadata('foo', self::class, false, false, null),
new ArgumentMetadata('bar', 'array', false, false, null),
new ArgumentMetadata('baz', 'callable', false, false, null),
new ArgumentMetadata('foo', self::class, false, false, null, controllerName: $this::class.'::signature1'),
new ArgumentMetadata('bar', 'array', false, false, null, controllerName: $this::class.'::signature1'),
new ArgumentMetadata('baz', 'callable', false, false, null, controllerName: $this::class.'::signature1'),
], $arguments);
}
@@ -120,10 +120,10 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata([new NullableController(), 'action']);
$this->assertEquals([
new ArgumentMetadata('foo', 'string', false, false, null, true),
new ArgumentMetadata('bar', \stdClass::class, false, false, null, true),
new ArgumentMetadata('baz', 'string', false, true, 'value', true),
new ArgumentMetadata('last', 'string', false, true, '', false),
new ArgumentMetadata('foo', 'string', false, false, null, true, controllerName: NullableController::class.'::action'),
new ArgumentMetadata('bar', \stdClass::class, false, false, null, true, controllerName: NullableController::class.'::action'),
new ArgumentMetadata('baz', 'string', false, true, 'value', true, controllerName: NullableController::class.'::action'),
new ArgumentMetadata('last', 'string', false, true, '', false, controllerName: NullableController::class.'::action'),
], $arguments);
}
@@ -132,7 +132,7 @@ class ArgumentMetadataFactoryTest extends TestCase
$arguments = $this->factory->createArgumentMetadata([new AttributeController(), 'action']);
$this->assertEquals([
new ArgumentMetadata('baz', 'string', false, false, null, false, [new Foo('bar')]),
new ArgumentMetadata('baz', 'string', false, false, null, false, [new Foo('bar')], controllerName: AttributeController::class.'::action'),
], $arguments);
}
@@ -146,8 +146,8 @@ class ArgumentMetadataFactoryTest extends TestCase
{
$arguments = $this->factory->createArgumentMetadata([new AttributeController(), 'issue41478']);
$this->assertEquals([
new ArgumentMetadata('baz', 'string', false, false, null, false, [new Foo('bar')]),
new ArgumentMetadata('bat', 'string', false, false, null, false, []),
new ArgumentMetadata('baz', 'string', false, false, null, false, [new Foo('bar')], controllerName: AttributeController::class.'::issue41478'),
new ArgumentMetadata('bat', 'string', false, false, null, false, [], controllerName: AttributeController::class.'::issue41478'),
], $arguments);
}