Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d0effcd

Browse filesBrowse files
feature #28865 [Routing] allow using compiled matchers and generators without dumping PHP code (nicolas-grekas)
This PR was merged into the 4.3-dev branch. Discussion ---------- [Routing] allow using compiled matchers and generators without dumping PHP code | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | #29590 | License | MIT | Doc PR | symfony/symfony-docs#10790 This is a resurrection of #25909 to make matcher+generator dumpers output PHP arrays instead of PHP code. Don't be fooled by the diff stats, it's mostly fixtures. This PR should contribute to making the Routing component easier to use standalone. On the way back from SFLive USA. ![image](https://user-images.githubusercontent.com/243674/46920076-784e1b80-cf9d-11e8-86e7-850fffb409de.png) Commits ------- f0a519a [Routing] allow using compiled matchers and generators without dumping PHP code
2 parents 4fbb6e5 + f0a519a commit d0effcd
Copy full SHA for d0effcd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

51 files changed

+5144
-490
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@
8282
use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;
8383
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
8484
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
85+
use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper;
8586
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
8687
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
88+
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
89+
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
8790
use Symfony\Component\Security\Core\Security;
8891
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
8992
use Symfony\Component\Serializer\Encoder\DecoderInterface;
@@ -754,6 +757,12 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co
754757
if (isset($config['type'])) {
755758
$argument['resource_type'] = $config['type'];
756759
}
760+
if (!class_exists(CompiledUrlMatcher::class)) {
761+
$argument['matcher_class'] = $argument['matcher_base_class'];
762+
$argument['matcher_dumper_class'] = PhpMatcherDumper::class;
763+
$argument['generator_class'] = $argument['generator_base_class'];
764+
$argument['generator_dumper_class'] = PhpGeneratorDumper::class;
765+
}
757766
$router->replaceArgument(2, $argument);
758767

759768
$container->setParameter('request_listener.http_port', $config['http_port']);

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@
5959
<argument type="collection">
6060
<argument key="cache_dir">%kernel.cache_dir%</argument>
6161
<argument key="debug">%kernel.debug%</argument>
62-
<argument key="generator_class">Symfony\Component\Routing\Generator\UrlGenerator</argument>
62+
<argument key="generator_class">Symfony\Component\Routing\Generator\CompiledUrlGenerator</argument>
6363
<argument key="generator_base_class">Symfony\Component\Routing\Generator\UrlGenerator</argument>
64-
<argument key="generator_dumper_class">Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper</argument>
64+
<argument key="generator_dumper_class">Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper</argument>
6565
<argument key="generator_cache_class">%router.cache_class_prefix%UrlGenerator</argument>
66-
<argument key="matcher_class">Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher</argument>
66+
<argument key="matcher_class">Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher</argument>
6767
<argument key="matcher_base_class">Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher</argument>
68-
<argument key="matcher_dumper_class">Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper</argument>
68+
<argument key="matcher_dumper_class">Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper</argument>
6969
<argument key="matcher_cache_class">%router.cache_class_prefix%UrlMatcher</argument>
7070
</argument>
7171
<argument type="service" id="router.request_context" on-invalid="ignore" />
+39Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Routing;
13+
14+
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
15+
use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;
16+
17+
/**
18+
* @author Fabien Potencier <fabien@symfony.com>
19+
*
20+
* @internal
21+
*/
22+
class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function redirect($path, $route, $scheme = null)
28+
{
29+
return [
30+
'_controller' => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction',
31+
'path' => $path,
32+
'permanent' => true,
33+
'scheme' => $scheme,
34+
'httpPort' => $this->context->getHttpPort(),
35+
'httpsPort' => $this->context->getHttpsPort(),
36+
'_route' => $route,
37+
];
38+
}
39+
}

‎src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableUrlMatcher.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableUrlMatcher.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Routing;
1313

14+
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3.', RedirectableUrlMatcher::class), E_USER_DEPRECATED);
15+
1416
use Symfony\Component\Routing\Matcher\RedirectableUrlMatcher as BaseMatcher;
1517

1618
/**
1719
* @author Fabien Potencier <fabien@symfony.com>
20+
*
21+
* @deprecated since Symfony 4.3
1822
*/
1923
class RedirectableUrlMatcher extends BaseMatcher
2024
{
+72Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Routing;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher;
16+
use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
17+
use Symfony\Component\Routing\RequestContext;
18+
use Symfony\Component\Routing\Route;
19+
use Symfony\Component\Routing\RouteCollection;
20+
21+
/**
22+
* @requires function \Symfony\Component\Routing\Matcher\CompiledUrlMatcher::match
23+
*/
24+
class RedirectableCompiledUrlMatcherTest extends TestCase
25+
{
26+
public function testRedirectWhenNoSlash()
27+
{
28+
$routes = new RouteCollection();
29+
$routes->add('foo', new Route('/foo/'));
30+
31+
$matcher = $this->getMatcher($routes, $context = new RequestContext());
32+
33+
$this->assertEquals([
34+
'_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction',
35+
'path' => '/foo/',
36+
'permanent' => true,
37+
'scheme' => null,
38+
'httpPort' => $context->getHttpPort(),
39+
'httpsPort' => $context->getHttpsPort(),
40+
'_route' => 'foo',
41+
],
42+
$matcher->match('/foo')
43+
);
44+
}
45+
46+
public function testSchemeRedirect()
47+
{
48+
$routes = new RouteCollection();
49+
$routes->add('foo', new Route('/foo', [], [], [], '', ['https']));
50+
51+
$matcher = $this->getMatcher($routes, $context = new RequestContext());
52+
53+
$this->assertEquals([
54+
'_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction',
55+
'path' => '/foo',
56+
'permanent' => true,
57+
'scheme' => 'https',
58+
'httpPort' => $context->getHttpPort(),
59+
'httpsPort' => $context->getHttpsPort(),
60+
'_route' => 'foo',
61+
],
62+
$matcher->match('/foo')
63+
);
64+
}
65+
66+
private function getMatcher(RouteCollection $routes, RequestContext $context)
67+
{
68+
$dumper = new CompiledUrlMatcherDumper($routes);
69+
70+
return new RedirectableCompiledUrlMatcher($dumper->getCompiledRoutes(), $context);
71+
}
72+
}

‎src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
use Symfony\Component\Routing\Route;
1818
use Symfony\Component\Routing\RouteCollection;
1919

20+
/**
21+
* @group legacy
22+
*/
2023
class RedirectableUrlMatcherTest extends TestCase
2124
{
2225
public function testRedirectWhenNoSlash()

‎src/Symfony/Component/Routing/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/CHANGELOG.md
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGELOG
22
=========
33

4+
4.3.0
5+
-----
6+
7+
* added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper`
8+
* added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper`
9+
* deprecated `PhpUrlGeneratorDumped` and `PhpMatcherDumper`
10+
411
4.2.0
512
-----
613

+58Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Generator;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\Routing\Exception\RouteNotFoundException;
16+
use Symfony\Component\Routing\RequestContext;
17+
18+
/**
19+
* Generates URLs based on rules dumped by CompiledUrlGeneratorDumper.
20+
*/
21+
class CompiledUrlGenerator extends UrlGenerator
22+
{
23+
private $compiledRoutes = [];
24+
private $defaultLocale;
25+
26+
public function __construct(array $compiledRoutes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null)
27+
{
28+
$this->compiledRoutes = $compiledRoutes;
29+
$this->context = $context;
30+
$this->logger = $logger;
31+
$this->defaultLocale = $defaultLocale;
32+
}
33+
34+
public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
35+
{
36+
$locale = $parameters['_locale']
37+
?? $this->context->getParameter('_locale')
38+
?: $this->defaultLocale;
39+
40+
if (null !== $locale) {
41+
do {
42+
if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
43+
unset($parameters['_locale']);
44+
$name .= '.'.$locale;
45+
break;
46+
}
47+
} while (false !== $locale = strstr($locale, '_', true));
48+
}
49+
50+
if (!isset($this->compiledRoutes[$name])) {
51+
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
52+
}
53+
54+
list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name];
55+
56+
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
57+
}
58+
}
+73Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Generator\Dumper;
13+
14+
use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
15+
16+
/**
17+
* CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator.
18+
*
19+
* @author Fabien Potencier <fabien@symfony.com>
20+
* @author Tobias Schultze <http://tobion.de>
21+
* @author Nicolas Grekas <p@tchwork.com>
22+
*/
23+
class CompiledUrlGeneratorDumper extends GeneratorDumper
24+
{
25+
public function getCompiledRoutes(): array
26+
{
27+
$compiledRoutes = [];
28+
foreach ($this->getRoutes()->all() as $name => $route) {
29+
$compiledRoute = $route->compile();
30+
31+
$compiledRoutes[$name] = [
32+
$compiledRoute->getVariables(),
33+
$route->getDefaults(),
34+
$route->getRequirements(),
35+
$compiledRoute->getTokens(),
36+
$compiledRoute->getHostTokens(),
37+
$route->getSchemes(),
38+
];
39+
}
40+
41+
return $compiledRoutes;
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*/
47+
public function dump(array $options = [])
48+
{
49+
return <<<EOF
50+
<?php
51+
52+
// This file has been auto-generated by the Symfony Routing Component.
53+
54+
return [{$this->generateDeclaredRoutes()}
55+
];
56+
57+
EOF;
58+
}
59+
60+
/**
61+
* Generates PHP code representing an array of defined routes
62+
* together with the routes properties (e.g. requirements).
63+
*/
64+
private function generateDeclaredRoutes(): string
65+
{
66+
$routes = '';
67+
foreach ($this->getCompiledRoutes() as $name => $properties) {
68+
$routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties));
69+
}
70+
71+
return $routes;
72+
}
73+
}

‎src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php
+6-2Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111

1212
namespace Symfony\Component\Routing\Generator\Dumper;
1313

14-
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
14+
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "CompiledUrlGeneratorDumper" instead.', PhpGeneratorDumper::class), E_USER_DEPRECATED);
15+
16+
use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
1517

1618
/**
1719
* PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes.
1820
*
1921
* @author Fabien Potencier <fabien@symfony.com>
2022
* @author Tobias Schultze <http://tobion.de>
23+
*
24+
* @deprecated since Symfony 4.3, use CompiledUrlGeneratorDumper instead.
2125
*/
2226
class PhpGeneratorDumper extends GeneratorDumper
2327
{
@@ -92,7 +96,7 @@ private function generateDeclaredRoutes()
9296
$properties[] = $compiledRoute->getHostTokens();
9397
$properties[] = $route->getSchemes();
9498

95-
$routes .= sprintf(" '%s' => %s,\n", $name, PhpMatcherDumper::export($properties));
99+
$routes .= sprintf(" '%s' => %s,\n", $name, CompiledUrlMatcherDumper::export($properties));
96100
}
97101
$routes .= ' ]';
98102

+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Matcher;
13+
14+
use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait;
15+
use Symfony\Component\Routing\RequestContext;
16+
17+
/**
18+
* Matches URLs based on rules dumped by CompiledUrlMatcherDumper.
19+
*
20+
* @author Nicolas Grekas <p@tchwork.com>
21+
*/
22+
class CompiledUrlMatcher extends UrlMatcher
23+
{
24+
use CompiledUrlMatcherTrait;
25+
26+
public function __construct(array $compiledRoutes, RequestContext $context)
27+
{
28+
$this->context = $context;
29+
list($this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition) = $compiledRoutes;
30+
}
31+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.