Skip to content

Commit 91479c4

Browse files
[Routing] Add {foo:bar} syntax to define a mapping between a route parameter and its corresponding request attribute
1 parent 9f15bda commit 91479c4

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.1
5+
---
6+
7+
* Add `{foo:bar}` syntax to define a mapping between a route parameter and its corresponding request attribute
8+
49
7.0
510
---
611

Matcher/UrlMatcher.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ protected function getAttributes(Route $route, string $name, array $attributes):
197197
}
198198
$attributes['_route'] = $name;
199199

200+
if ($mapping = $route->getOption('mapping')) {
201+
$attributes['_route_mapping'] = $mapping;
202+
}
203+
200204
return $this->mergeDefaults($attributes, $defaults);
201205
}
202206

Route.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,20 +412,31 @@ public function compile(): CompiledRoute
412412

413413
private function extractInlineDefaultsAndRequirements(string $pattern): string
414414
{
415-
if (false === strpbrk($pattern, '?<')) {
415+
if (false === strpbrk($pattern, '?<:')) {
416416
return $pattern;
417417
}
418418

419-
return preg_replace_callback('#\{(!?)([\w\x80-\xFF]++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) {
419+
$mapping = $this->getDefault('_route_mapping') ?? [];
420+
421+
$pattern = preg_replace_callback('#\{(!?)([\w\x80-\xFF]++)(:[\w\x80-\xFF]++)?(<.*?>)?(\?[^\}]*+)?\}#', function ($m) use (&$mapping) {
422+
if (isset($m[5][0])) {
423+
$this->setDefault($m[2], '?' !== $m[5] ? substr($m[5], 1) : null);
424+
}
420425
if (isset($m[4][0])) {
421-
$this->setDefault($m[2], '?' !== $m[4] ? substr($m[4], 1) : null);
426+
$this->setRequirement($m[2], substr($m[4], 1, -1));
422427
}
423428
if (isset($m[3][0])) {
424-
$this->setRequirement($m[2], substr($m[3], 1, -1));
429+
$mapping[$m[2]] = substr($m[3], 1);
425430
}
426431

427432
return '{'.$m[1].$m[2].'}';
428433
}, $pattern);
434+
435+
if ($mapping) {
436+
$this->setDefault('_route_mapping', $mapping);
437+
}
438+
439+
return $pattern;
429440
}
430441

431442
private function sanitizeRequirement(string $key, string $regex): string

Tests/Matcher/UrlMatcherTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,23 @@ public function testUtf8VarName()
10001000
$this->assertEquals(['_route' => 'foo', 'bär' => 'baz', 'bäz' => 'foo'], $matcher->match('/foo/baz'));
10011001
}
10021002

1003+
public function testMapping()
1004+
{
1005+
$collection = new RouteCollection();
1006+
$collection->add('a', new Route('/conference/{slug:conference}'));
1007+
1008+
$matcher = $this->getUrlMatcher($collection);
1009+
1010+
$expected = [
1011+
'_route' => 'a',
1012+
'slug' => 'vienna-2024',
1013+
'_route_mapping' => [
1014+
'slug' => 'conference',
1015+
],
1016+
];
1017+
$this->assertEquals($expected, $matcher->match('/conference/vienna-2024'));
1018+
}
1019+
10031020
protected function getUrlMatcher(RouteCollection $routes, ?RequestContext $context = null)
10041021
{
10051022
return new UrlMatcher($routes, $context ?? new RequestContext());

0 commit comments

Comments
 (0)