Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0f9246f

Browse files
feature #26518 [Routing] Allow inline definition of requirements and defaults (nicolas-grekas)
This PR was merged into the 4.1-dev branch. Discussion ---------- [Routing] Allow inline definition of requirements and defaults | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #26481 | License | MIT | Doc PR | - ``` {bar} -- no requirement, no default value {bar<.*>} -- with requirement, no default value {bar?default_value} -- no requirement, with default value {bar<.*>?default_value} -- with requirement and default value {bar?} -- no requirement, with default value of null {bar<.*>?} -- with requirement and default value of null ``` Details: * Requirements and default values are not escaped in any way. This is valid -> `@Route("/foo/{bar<>>?<>}")` (requirements = `>` and default value = `<>`) * Because of the lack of escaping, you can't use a closing brace (`}`) inside the default value (wrong -> `@Route("/foo/{bar<\d+>?aa}bb}")`) but you can use it inside requirements (correct -> `@Route("/foo/{bar<\d{3}>}")`). * PHP constants are not supported (use the traditional `defaults` syntax for that) * ... Commits ------- 67559e1 [Routing] Allow inline definition of requirements and defaults
2 parents e32c1da + 67559e1 commit 0f9246f

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

src/Symfony/Component/Routing/Route.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ class Route implements \Serializable
5353
public function __construct(string $path, array $defaults = array(), array $requirements = array(), array $options = array(), ?string $host = '', $schemes = array(), $methods = array(), ?string $condition = '')
5454
{
5555
$this->setPath($path);
56-
$this->setDefaults($defaults);
57-
$this->setRequirements($requirements);
56+
$this->addDefaults($defaults);
57+
$this->addRequirements($requirements);
5858
$this->setOptions($options);
5959
$this->setHost($host);
6060
$this->setSchemes($schemes);
@@ -123,6 +123,19 @@ public function getPath()
123123
*/
124124
public function setPath($pattern)
125125
{
126+
if (false !== strpbrk($pattern, '?<')) {
127+
$pattern = preg_replace_callback('#\{(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) {
128+
if (isset($m[3][0])) {
129+
$this->setDefault($m[1], '?' !== $m[3] ? substr($m[3], 1) : null);
130+
}
131+
if (isset($m[2][0])) {
132+
$this->setRequirement($m[1], substr($m[2], 1, -1));
133+
}
134+
135+
return '{'.$m[1].'}';
136+
}, $pattern);
137+
}
138+
126139
// A pattern must start with a slash and must not have multiple slashes at the beginning because the
127140
// generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
128141
$this->path = '/'.ltrim(trim($pattern), '/');

src/Symfony/Component/Routing/Tests/RouteTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,22 @@ public function testSerialize()
203203
$this->assertNotSame($route, $unserialized);
204204
}
205205

206+
public function testInlineDefaultAndRequirement()
207+
{
208+
$this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', null), new Route('/foo/{bar?}'));
209+
$this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?baz}'));
210+
$this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz<buz>'), new Route('/foo/{bar?baz<buz>}'));
211+
$this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?}', array('bar' => 'baz')));
212+
213+
$this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '.*'), new Route('/foo/{bar<.*>}'));
214+
$this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '>'), new Route('/foo/{bar<>>}'));
215+
$this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '\d+'), new Route('/foo/{bar<.*>}', array(), array('bar' => '\d+')));
216+
$this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '[a-z]{2}'), new Route('/foo/{bar<[a-z]{2}>}'));
217+
218+
$this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', null)->setRequirement('bar', '.*'), new Route('/foo/{bar<.*>?}'));
219+
$this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', '<>')->setRequirement('bar', '>'), new Route('/foo/{bar<>>?<>}'));
220+
}
221+
206222
/**
207223
* Tests that the compiled version is also serialized to prevent the overhead
208224
* of compiling it again after unserialize.

0 commit comments

Comments
 (0)