diff --git a/UPGRADE-7.4.md b/UPGRADE-7.4.md index f6624c65af8f8..ff4dde989237d 100644 --- a/UPGRADE-7.4.md +++ b/UPGRADE-7.4.md @@ -64,6 +64,11 @@ Mime * Deprecate implementing `__sleep/wakeup()` on `AbstractPart` implementations; use `__(un)serialize()` instead +Routing +------- + + * Deprecate `getEnv()` and `setEnv()` methods of the `Symfony\Component\Routing\Attribute\Route` class in favor of the plurialized `getEnvs()` and `setEnvs()` methods + Security -------- diff --git a/src/Symfony/Component/Routing/Attribute/Route.php b/src/Symfony/Component/Routing/Attribute/Route.php index 003bbe64f5a83..1ad37e177ef30 100644 --- a/src/Symfony/Component/Routing/Attribute/Route.php +++ b/src/Symfony/Component/Routing/Attribute/Route.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Routing\Attribute; +use Symfony\Component\Routing\Exception\LogicException; + /** * @author Fabien Potencier * @author Alexander M. Turek @@ -21,6 +23,8 @@ class Route private ?string $path = null; private array $localizedPaths = []; private array $methods; + /** @var string[] */ + private array $env; private array $schemes; /** * @var (string|DeprecatedAlias)[] @@ -42,7 +46,7 @@ class Route * @param string|null $format The format returned by the route (i.e. "json", "xml") * @param bool|null $utf8 Whether the route accepts UTF-8 in its parameters * @param bool|null $stateless Whether the route is defined as stateless or stateful, @see https://symfony.com/doc/current/routing.html#stateless-routes - * @param string|null $env The env in which the route is defined (i.e. "dev", "test", "prod") + * @param string|string[]|null $env The env(s) in which the route is defined (i.e. "dev", "test", "prod", ["dev", "test"]) * @param string|DeprecatedAlias|(string|DeprecatedAlias)[] $alias The list of aliases for this route */ public function __construct( @@ -60,7 +64,7 @@ public function __construct( ?string $format = null, ?bool $utf8 = null, ?bool $stateless = null, - private ?string $env = null, + string|array|null $env = null, string|DeprecatedAlias|array $alias = [], ) { if (\is_array($path)) { @@ -71,6 +75,7 @@ public function __construct( $this->setMethods($methods); $this->setSchemes($schemes); $this->setAliases($alias); + $this->setEnvs((array) $env); if (null !== $locale) { $this->defaults['_locale'] = $locale; @@ -199,12 +204,37 @@ public function getPriority(): ?int return $this->priority; } + /** + * @deprecated since Symfony 7.4, use the {@see setEnvs()} method instead + */ public function setEnv(?string $env): void { - $this->env = $env; + trigger_deprecation('symfony/routing', '7.4', 'The "%s()" method is deprecated, use "setEnvs()" instead.', __METHOD__); + $this->env = (array) $env; } + /** + * @deprecated since Symfony 7.4, use {@see getEnvs()} method instead + */ public function getEnv(): ?string + { + trigger_deprecation('symfony/routing', '7.4', 'The "%s()" method is deprecated, use "getEnvs()" instead.', __METHOD__); + if (!$this->env) { + return null; + } + if (\count($this->env) > 1) { + throw new LogicException(\sprintf('The "env" property has %d environments. Use "getEnvs()" to get all of them.', \count($this->env))); + } + + return $this->env[0]; + } + + public function setEnvs(array|string $env): void + { + $this->env = (array) $env; + } + + public function getEnvs(): array { return $this->env; } diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index 4ef96d53232fe..3496520b323c4 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Allow query-specific parameters in `UrlGenerator` using `_query` + * Add support of multiple env names in the `Symfony\Component\Routing\Attribute\Route` attribute 7.3 --- diff --git a/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php b/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php index 254582bf35584..5fdd7906084b7 100644 --- a/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php @@ -105,7 +105,7 @@ public function load(mixed $class, ?string $type = null): RouteCollection $globals = $this->getGlobals($class); $collection = new RouteCollection(); $collection->addResource(new FileResource($class->getFileName())); - if ($globals['env'] && $this->env !== $globals['env']) { + if ($globals['env'] && !\in_array($this->env, $globals['env'], true)) { return $collection; } $fqcnAlias = false; @@ -161,7 +161,7 @@ public function load(mixed $class, ?string $type = null): RouteCollection */ protected function addRoute(RouteCollection $collection, object $attr, array $globals, \ReflectionClass $class, \ReflectionMethod $method): void { - if ($attr->getEnv() && $attr->getEnv() !== $this->env) { + if ($attr->getEnvs() && !\in_array($this->env, $attr->getEnvs(), true)) { return; } @@ -338,7 +338,7 @@ protected function getGlobals(\ReflectionClass $class): array } $globals['priority'] = $attr->getPriority() ?? 0; - $globals['env'] = $attr->getEnv(); + $globals['env'] = $attr->getEnvs(); foreach ($globals['requirements'] as $placeholder => $requirement) { if (\is_int($placeholder)) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures/RouteWithEnv.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures/RouteWithEnv.php index 31f6c39bca657..c8f82fdf9ee7b 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures/RouteWithEnv.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures/RouteWithEnv.php @@ -16,4 +16,19 @@ public function action() public function action2() { } + + #[Route(path: '/path3', name: 'action3', env: ['some-other-env', 'some-other-env-two'])] + public function action3() + { + } + + #[Route(path: '/path4', name: 'action4', env: null)] + public function action4() + { + } + + #[Route(path: '/path5', name: 'action5', env: ['some-other-env', 'some-env'])] + public function action5() + { + } } diff --git a/src/Symfony/Component/Routing/Tests/Loader/AttributeClassLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AttributeClassLoaderTest.php index 2fa00e07f9f80..8ad0ede6d5132 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AttributeClassLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AttributeClassLoaderTest.php @@ -330,8 +330,10 @@ public function testWhenEnv() $this->setUp('some-env'); $routes = $this->loader->load(RouteWithEnv::class); - $this->assertCount(1, $routes); + $this->assertCount(3, $routes); $this->assertSame('/path', $routes->get('action')->getPath()); + $this->assertSame('/path4', $routes->get('action4')->getPath()); + $this->assertSame('/path5', $routes->get('action5')->getPath()); } public function testMethodsAndSchemes()