Skip to content

Commit 01ee74a

Browse files
loks0nclaude
andcommitted
Add 'params' frame-local injection
Mirrors the 'route' injection: hooks can do ->inject('params') to receive the resolved path params (array<string, string>) for the current dispatch frame. Skips shared context for the same reason 'route' does — nested execute() calls (sub-request dispatch) can't trample each other. Refactor: collapse the per-name special-cases into a frame-local map for clarity. Both 'route' and 'params' come from the dispatch frame; the map makes that explicit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 607abe2 commit 01ee74a

2 files changed

Lines changed: 47 additions & 8 deletions

File tree

src/Http/Http.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -720,15 +720,18 @@ protected function getArguments(Hook $hook, array $values, array $requestParams,
720720
$arguments[$param['order']] = $value;
721721
}
722722

723-
foreach ($hook->getInjections() as $injection) {
724-
// 'route' is frame-local: pass the dispatch frame's matched Route
725-
// through directly instead of routing through shared context.
726-
if ($injection['name'] === 'route') {
727-
$arguments[$injection['order']] = $route;
728-
continue;
729-
}
723+
// Frame-local injections come from the dispatch frame, not the
724+
// per-request context. Writing them to context would leak across
725+
// nested execute() calls (e.g. sub-request dispatch).
726+
$frameLocals = [
727+
'route' => $route,
728+
'params' => $values,
729+
];
730730

731-
$arguments[$injection['order']] = $this->adapter->context()->get($injection['name']);
731+
foreach ($hook->getInjections() as $injection) {
732+
$arguments[$injection['order']] = \array_key_exists($injection['name'], $frameLocals)
733+
? $frameLocals[$injection['name']]
734+
: $this->adapter->context()->get($injection['name']);
732735
}
733736

734737
return $arguments;

tests/HttpTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,42 @@ public function testSubrequestRestoresOuterRoute(): void
741741
$this->assertSame(['/inner', '/outer'], $captured);
742742
}
743743

744+
public function testParamsInjection(): void
745+
{
746+
$_SERVER['REQUEST_METHOD'] = 'GET';
747+
$_SERVER['REQUEST_URI'] = '/users/abc-123/posts/42';
748+
749+
$captured = null;
750+
751+
Http::get('/users/:id/posts/:postId')
752+
->inject('params')
753+
->action(function (array $params) use (&$captured) {
754+
$captured = $params;
755+
});
756+
757+
$this->http->execute(new Request(), new Response());
758+
759+
$this->assertSame(['id' => 'abc-123', 'postId' => '42'], $captured);
760+
}
761+
762+
public function testParamsInjectionEmptyForStaticRoute(): void
763+
{
764+
$_SERVER['REQUEST_METHOD'] = 'GET';
765+
$_SERVER['REQUEST_URI'] = '/static';
766+
767+
$captured = null;
768+
769+
Http::get('/static')
770+
->inject('params')
771+
->action(function (array $params) use (&$captured) {
772+
$captured = $params;
773+
});
774+
775+
$this->http->execute(new Request(), new Response());
776+
777+
$this->assertSame([], $captured);
778+
}
779+
744780
public function testWildcardRoute(): void
745781
{
746782
$method = $_SERVER['REQUEST_METHOD'] ?? null;

0 commit comments

Comments
 (0)