Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commitdf3255c

Browse files
committed
Merge branch 'release/0.8.5'
2 parentsd1f66ca +7afa7f0 commitdf3255c

File tree

6 files changed

+172
-14
lines changed

6 files changed

+172
-14
lines changed

‎.version.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"strategy":"semver",
33
"major":0,
44
"minor":8,
5-
"patch":4,
5+
"patch":5,
66
"build":0
77
}

‎VERSIONLOG.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
##0.8.5 2025-11-27
2+
* Added wildcard support for route parameters.
3+
14
##0.8.4 2025-11-24
25

36
##0.8.3 2025-11-12

‎src/Routing/Filters/RateLimitFilter.php‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,19 @@ protected function checkRateLimit( RouteMap $route ): void
9999
// Get rate limit info
100100
$remaining =$this->_storage->getRemainingAttempts($key,$limit,$window );
101101
$resetTime =$this->_storage->getResetTime($key,$window );
102+
$attempts =$limit -$remaining;
102103

103104
Log::warning("Rate limit exceeded for key:$key" );
104105

106+
// Emit rate limit exceeded event
107+
\Neuron\Application\CrossCutting\Event::emit(new \Neuron\Mvc\Events\RateLimitExceededEvent(
108+
$this->getClientIp(),
109+
$route->getPath(),
110+
$limit,
111+
$window,
112+
$attempts
113+
) );
114+
105115
// Send rate limit response and exit
106116
RateLimitResponse::send($limit,$remaining,$resetTime );
107117
exit;

‎src/Routing/RouteMap.php‎

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,22 +175,37 @@ public function parseParams(): array
175175

176176
foreach($partsas$part )
177177
{
178-
if(substr($part,0,1 ) ==':' )
178+
if(substr($part,0,1 ) =='*' )
179179
{
180+
// Wildcard parameter - captures all remaining URI segments
180181
$param =substr($part,1 );
181182

182183
$this->checkForDuplicateParams($param,$details );
183184

184185
$details[] = [
185-
'param' =>$param,
186-
'action' =>false
186+
'param' =>$param,
187+
'action' =>false,
188+
'wildcard' =>true
189+
];
190+
}
191+
elseif(substr($part,0,1 ) ==':' )
192+
{
193+
$param =substr($part,1 );
194+
195+
$this->checkForDuplicateParams($param,$details );
196+
197+
$details[] = [
198+
'param' =>$param,
199+
'action' =>false,
200+
'wildcard' =>false
187201
];
188202
}
189203
else
190204
{
191205
$details[] = [
192-
'param' =>false,
193-
'action' =>$part
206+
'param' =>false,
207+
'action' =>$part,
208+
'wildcard' =>false
194209
];
195210
}
196211
}

‎src/Routing/Router.php‎

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,18 @@ public function put( string $route, $function, ?string $filter = null ) : RouteM
173173
*/
174174
protectedfunctionisRouteWithParams(RouteMap$route ) :bool
175175
{
176-
returnstrpos($route->Path,':' ) ==true;
176+
returnstrpos($route->Path,':' ) !==false ||strpos($route->Path,'*' ) !==false;
177+
}
178+
179+
/**
180+
* Check if route contains a wildcard parameter
181+
*
182+
* @param RouteMap $route
183+
* @return bool
184+
*/
185+
protectedfunctionhasWildcard(RouteMap$route ) :bool
186+
{
187+
returnstrpos($route->Path,'*' ) !==false;
177188
}
178189

179190
/**
@@ -207,7 +218,15 @@ protected function processRoute( RouteMap $route, $uri ) : ?array
207218

208219
$routeSegments =count(explode('/',$route->Path ) );
209220

210-
if($segments ==$routeSegments )
221+
// Wildcard routes need >= segments, normal routes need exact match
222+
if($this->hasWildcard($route ) )
223+
{
224+
if($segments >=$routeSegments )
225+
{
226+
return$this->processRouteWithParameters($route,$uri );
227+
}
228+
}
229+
elseif($segments ==$routeSegments )
211230
{
212231
return$this->processRouteWithParameters($route,$uri );
213232
}
@@ -257,22 +276,30 @@ protected function extractRouteParams( string $uri, array $details ) : array
257276
$params = [];
258277
$iOffset =0;
259278

260-
foreach($uriPartsas$part )
279+
foreach($detailsas$index =>$detail )
261280
{
262-
if($iOffset >=count($details ) )
281+
if($iOffset >=count($uriParts ) )
263282
{
264283
return [];
265284
}
266285

267-
$action =$details[$iOffset ]['action' ];
286+
$action =$detail['action' ];
287+
$isWildcard =$detail['wildcard' ] ??false;
268288

269-
if($action &&$action !=$part )
289+
if($isWildcard )
290+
{
291+
// Wildcard parameter - capture all remaining URI segments
292+
$remainingParts =array_slice($uriParts,$iOffset );
293+
$params[$detail['param' ] ] =implode('/',$remainingParts );
294+
break;// Wildcard consumes rest of URI
295+
}
296+
elseif($action &&$action !=$uriParts[$iOffset ] )
270297
{
271298
return [];
272299
}
273-
else
300+
elseif($detail['param' ] )
274301
{
275-
$params[$details[$iOffset ]['param' ] ] =$part;
302+
$params[$detail['param' ] ] =$uriParts[$iOffset ];
276303
}
277304

278305
$iOffset++;

‎tests/unit/RouterTest.php‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,4 +438,107 @@ public function testPayload()
438438

439439
$this->assertEquals('Controller@method',$Payload );
440440
}
441+
442+
publicfunctiontestWildcardRoute()
443+
{
444+
$this->Router->get('/md/*page',
445+
function($parameters )
446+
{
447+
return$parameters['page' ];
448+
}
449+
);
450+
451+
$Route =$this->Router->getRoute(
452+
Routing\RequestMethod::GET,
453+
'/md/authentication'
454+
);
455+
456+
$this->assertNotNull($Route );
457+
$this->assertEquals('/md/*page',$Route->Path );
458+
459+
$test =$this->Router->run(
460+
[
461+
'route' =>'/md/authentication',
462+
'type' =>'GET'
463+
]
464+
);
465+
466+
$this->assertEquals('authentication',$test );
467+
}
468+
469+
publicfunctiontestWildcardRouteMultipleSegments()
470+
{
471+
$this->Router->get('/md/*page',
472+
function($parameters )
473+
{
474+
return$parameters['page' ];
475+
}
476+
);
477+
478+
$test =$this->Router->run(
479+
[
480+
'route' =>'/md/cms/guides/authentication',
481+
'type' =>'GET'
482+
]
483+
);
484+
485+
$this->assertEquals('cms/guides/authentication',$test );
486+
}
487+
488+
publicfunctiontestWildcardRouteSingleSegment()
489+
{
490+
$this->Router->get('/md/*page',
491+
function($parameters )
492+
{
493+
return$parameters['page' ];
494+
}
495+
);
496+
497+
$test =$this->Router->run(
498+
[
499+
'route' =>'/md/index',
500+
'type' =>'GET'
501+
]
502+
);
503+
504+
$this->assertEquals('index',$test );
505+
}
506+
507+
publicfunctiontestWildcardWithStaticPrefix()
508+
{
509+
$this->Router->get('/api/v1/*endpoint',
510+
function($parameters )
511+
{
512+
return'v1:' .$parameters['endpoint' ];
513+
}
514+
);
515+
516+
$test =$this->Router->run(
517+
[
518+
'route' =>'/api/v1/users/123/posts',
519+
'type' =>'GET'
520+
]
521+
);
522+
523+
$this->assertEquals('v1:users/123/posts',$test );
524+
}
525+
526+
publicfunctiontestWildcardRouteDeepPath()
527+
{
528+
$this->Router->get('/docs/*path',
529+
function($parameters )
530+
{
531+
return$parameters['path' ];
532+
}
533+
);
534+
535+
$test =$this->Router->run(
536+
[
537+
'route' =>'/docs/cms/reference/events/cache-hit',
538+
'type' =>'GET'
539+
]
540+
);
541+
542+
$this->assertEquals('cms/reference/events/cache-hit',$test );
543+
}
441544
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp