feature #40266 [Routing] Construct Route annotations using named arguments (derrabus)
This PR was merged into the 5.3-dev branch.
Discussion
----------
[Routing] Construct Route annotations using named arguments
| Q | A
| ------------- | ---
| Branch? | 5.x
| Bug fix? | no
| New feature? | no
| Deprecations? | yes
| Tickets | N/A
| License | MIT
| Doc PR | Not needed
This PR proposes to bump the `doctrine/annotations` library to 1.12 to gain access to its emulation layer for named arguments. Furthermore, constructing a `Route` annotation the old way by passing an array of parameters is deprecated.
### Reasons for this change
The constructors of our annotation classes have become unnecessarily complicated because we have to support two ways of calling them:
* An array of parameters, passed as first argument, because that's the default behavior `doctrine/annotations`.
* A set of named arguments because that's how PHP 8 attributes work.
Since we can now tell the Doctrine annotation reader to use named arguments as well, we can simplify the constructors of our annotations significantly.
### Drawback
After this change, there is no easy way anymore to construct instances of the `Route` annotation class directly on PHP 7. The PR has been built under the assumption that instances of this class are usually created using either Doctrine annotations or a PHP 8 attribute. Thus, most applications should be unaffected by this change.
Commits
-------
29b0f96046
[Routing] Construct Route annotations using named arguments
This commit is contained in:
commit
d54a1223f7
@ -69,6 +69,11 @@ PropertyInfo
|
||||
|
||||
* Deprecated the `Type::getCollectionKeyType()` and `Type::getCollectionValueType()` methods, use `Type::getCollectionKeyTypes()` and `Type::getCollectionValueTypes()` instead
|
||||
|
||||
Routing
|
||||
-------
|
||||
|
||||
* Deprecated creating instances of the `Route` annotation class by passing an array of parameters, use named arguments instead
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
|
@ -164,6 +164,7 @@ Routing
|
||||
* Removed `RouteCollectionBuilder`.
|
||||
* Added argument `$priority` to `RouteCollection::add()`
|
||||
* Removed the `RouteCompiler::REGEX_DELIMITER` constant
|
||||
* Removed the `$data` parameter from the constructor of the `Route` annotation class
|
||||
|
||||
Security
|
||||
--------
|
||||
|
@ -123,7 +123,7 @@
|
||||
"async-aws/sqs": "^1.0",
|
||||
"cache/integration-tests": "dev-master",
|
||||
"composer/package-versions-deprecated": "^1.8",
|
||||
"doctrine/annotations": "^1.10.4",
|
||||
"doctrine/annotations": "^1.12",
|
||||
"doctrine/cache": "~1.6",
|
||||
"doctrine/collections": "~1.0",
|
||||
"doctrine/data-fixtures": "^1.1",
|
||||
@ -151,6 +151,7 @@
|
||||
},
|
||||
"conflict": {
|
||||
"async-aws/core": "<1.5",
|
||||
"doctrine/annotations": "<1.12",
|
||||
"doctrine/dbal": "<2.10",
|
||||
"masterminds/html5": "<2.6",
|
||||
"phpdocumentor/reflection-docblock": "<3.2.2",
|
||||
|
@ -15,6 +15,7 @@ namespace Symfony\Component\Routing\Annotation;
|
||||
* Annotation class for @Route().
|
||||
*
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor
|
||||
* @Target({"CLASS", "METHOD"})
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@ -67,6 +68,8 @@ class Route
|
||||
$data = ['path' => $data];
|
||||
} elseif (!\is_array($data)) {
|
||||
throw new \TypeError(sprintf('"%s": Argument $data is expected to be a string or array, got "%s".', __METHOD__, get_debug_type($data)));
|
||||
} elseif ([] !== $data) {
|
||||
trigger_deprecation('symfony/routing', '5.3', 'Passing an array as first argument to "%s" is deprecated. Use named arguments instead.', __METHOD__);
|
||||
}
|
||||
if (null !== $path && !\is_string($path) && !\is_array($path)) {
|
||||
throw new \TypeError(sprintf('"%s": Argument $path is expected to be a string, array or null, got "%s".', __METHOD__, get_debug_type($path)));
|
||||
|
@ -6,6 +6,7 @@ CHANGELOG
|
||||
|
||||
* Already encoded slashes are not decoded nor double-encoded anymore when generating URLs
|
||||
* Add support for per-env configuration in loaders
|
||||
* Deprecate creating instances of the `Route` annotation class by passing an array of parameters
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
@ -12,16 +12,25 @@
|
||||
namespace Symfony\Component\Routing\Tests\Annotation;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class RouteTest extends TestCase
|
||||
{
|
||||
use ExpectDeprecationTrait;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testInvalidRouteParameter()
|
||||
{
|
||||
$this->expectException(\BadMethodCallException::class);
|
||||
new Route(['foo' => 'bar']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testTryingToSetLocalesDirectly()
|
||||
{
|
||||
$this->expectException(\BadMethodCallException::class);
|
||||
@ -29,18 +38,30 @@ class RouteTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
* @dataProvider getValidParameters
|
||||
*/
|
||||
public function testRouteParameters($parameter, $value, $getter)
|
||||
public function testRouteParameters(string $parameter, $value, string $getter)
|
||||
{
|
||||
$route = new Route(...[$parameter => $value]);
|
||||
$this->assertEquals($route->$getter(), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider getLegacyValidParameters
|
||||
*/
|
||||
public function testLegacyRouteParameters(string $parameter, $value, string $getter)
|
||||
{
|
||||
$this->expectDeprecation('Since symfony/routing 5.3: Passing an array as first argument to "Symfony\Component\Routing\Annotation\Route::__construct" is deprecated. Use named arguments instead.');
|
||||
|
||||
$route = new Route([$parameter => $value]);
|
||||
$this->assertEquals($route->$getter(), $value);
|
||||
}
|
||||
|
||||
public function getValidParameters()
|
||||
public function getValidParameters(): iterable
|
||||
{
|
||||
return [
|
||||
['value', '/Blog', 'getPath'],
|
||||
['requirements', ['locale' => 'en'], 'getRequirements'],
|
||||
['options', ['compiler_class' => 'RouteCompiler'], 'getOptions'],
|
||||
['name', 'blog_index', 'getName'],
|
||||
@ -49,7 +70,14 @@ class RouteTest extends TestCase
|
||||
['methods', ['GET', 'POST'], 'getMethods'],
|
||||
['host', '{locale}.example.com', 'getHost'],
|
||||
['condition', 'context.getMethod() == "GET"', 'getCondition'],
|
||||
['value', ['nl' => '/hier', 'en' => '/here'], 'getLocalizedPaths'],
|
||||
];
|
||||
}
|
||||
|
||||
public function getLegacyValidParameters(): iterable
|
||||
{
|
||||
yield from $this->getValidParameters();
|
||||
|
||||
yield ['value', '/Blog', 'getPath'];
|
||||
yield ['value', ['nl' => '/hier', 'en' => '/here'], 'getLocalizedPaths'];
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest
|
||||
|
||||
public function testLoadVariadic()
|
||||
{
|
||||
$route = new Route(['path' => '/path/to/{id}']);
|
||||
$route = new Route('/path/to/{id}');
|
||||
$this->reader->expects($this->once())->method('getClassAnnotation');
|
||||
$this->reader->expects($this->once())->method('getMethodAnnotations')
|
||||
->willReturn([$route]);
|
||||
|
@ -26,10 +26,11 @@
|
||||
"symfony/yaml": "^4.4|^5.0",
|
||||
"symfony/expression-language": "^4.4|^5.0",
|
||||
"symfony/dependency-injection": "^4.4|^5.0",
|
||||
"doctrine/annotations": "^1.10.4",
|
||||
"doctrine/annotations": "^1.12",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/annotations": "<1.12",
|
||||
"symfony/config": "<5.3",
|
||||
"symfony/dependency-injection": "<4.4",
|
||||
"symfony/yaml": "<4.4"
|
||||
|
Reference in New Issue
Block a user