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 0f9246f

Browse filesBrowse 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
Copy full SHA for 0f9246f

File tree

2 files changed

+31
-2
lines changed
Filter options

2 files changed

+31
-2
lines changed

‎src/Symfony/Component/Routing/Route.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Route.php
+15-2Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Tests/RouteTest.php
+16Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.