Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions src/adapter/ServerRequestAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@
*/
final class ServerRequestAdapter
{
/**
* Query parameters resolved from the PSR-7 ServerRequestInterface.
*
* @phpstan-var array<array-key, mixed>
*/
private array $queryParams = [];

/**
* Creates a new instance of the {@see ServerRequestAdapter} class.
*
Expand Down Expand Up @@ -83,7 +90,6 @@ public function getBodyParams(string $methodParam): array|object
{
$parsedBody = $this->psrRequest->getParsedBody();

// remove method parameter if present (same logic as parent)
if (is_array($parsedBody) && isset($parsedBody[$methodParam])) {
$bodyParams = $parsedBody;

Expand Down Expand Up @@ -219,14 +225,17 @@ public function getParsedBody(): array|object|null
}

/**
* Retrieves query parameters from the PSR-7 ServerRequestInterface.
* Retrieves query parameters from the PSR-7 ServerRequestInterface or cached values.
*
* Returns the query parameters as an associative array, providing direct access to all values present in the
* request URI.
* Returns the cached query parameters if previously set, otherwise retrieves them directly from the PSR-7
* ServerRequestInterface instance.
*
* @return array Associative array of query parameters from the request URI.
* This method provides immutable, type-safe access to query parameters for use in Yii2 Request component logic and
* controller actions.
*
* @phpstan-return array<mixed, mixed>
* @return array Query parameters as an associative array.
*
* @phpstan-return array<array-key, mixed>
*
* Usage example:
* ```php
Expand All @@ -235,6 +244,10 @@ public function getParsedBody(): array|object|null
*/
public function getQueryParams(): array
{
if ($this->queryParams !== []) {
return $this->queryParams;
}

return $this->psrRequest->getQueryParams();
}

Expand Down Expand Up @@ -395,9 +408,9 @@ public function resolve(Request $request): array
if ($result !== false) {
[$route, $params] = $result;

$combinedParams = $params + $this->psrRequest->getQueryParams();
$this->queryParams = $params + $this->psrRequest->getQueryParams();

return [$route, $combinedParams];
return [$route, $this->queryParams];
}

throw new NotFoundHttpException(Yii::t('yii', Message::PAGE_NOT_FOUND->getMessage()));
Expand Down
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ protected function statelessApplication(array $config = []): StatelessApplicatio
'enableStrictParsing' => false,
'enablePrettyUrl' => true,
'rules' => [
'site/query/<test:\w+>' => 'site/query',
'site/update/<id:\d+>' => 'site/update',
],
],
Expand Down
33 changes: 33 additions & 0 deletions tests/http/StatelessApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,39 @@ public function testReturnJsonResponseWithQueryParametersForSiteGetRoute(): void
);
}

public function testReturnJsonResponseWithQueryParamsForSiteQueryRoute(): void
{
$_GET = ['q' => '1'];
$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'site/query/foo?q=1',
];

$request = FactoryHelper::createServerRequestCreator()->createFromGlobals();

$app = $this->statelessApplication();

$response = $app->handle($request);

self::assertSame(
200,
$response->getStatusCode(),
"Response 'status code' should be '200' for 'site/query/foo?q=1' route in 'StatelessApplication'.",
);
self::assertSame(
'application/json; charset=UTF-8',
$response->getHeaders()['content-type'][0] ?? '',
"Response 'content-type' should be 'application/json; charset=UTF-8' for 'site/query/foo?q=1' route in " .
"'StatelessApplication'.",
);
self::assertSame(
'{"test":"foo","q":"1","queryParams":{"test":"foo","q":"1"}}',
$response->getBody()->getContents(),
"Response 'body' should contain valid JSON with route and query parameters for 'site/query/foo?q=1' in " .
"'StatelessApplication'.",
);
}

/**
* @throws InvalidConfigException if the configuration is invalid or incomplete.
*/
Expand Down
14 changes: 14 additions & 0 deletions tests/support/stub/SiteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,20 @@ public function actionPost(): mixed
return $this->request->post();
}

/**
* @phpstan-return array<array-key, mixed>
*/
public function actionQuery(string $test): array
{
$this->response->format = Response::FORMAT_JSON;

return [
'test' => $test,
'q' => $this->request->get('q'),
'queryParams' => $this->request->getQueryParams(),
];
}

/**
* @throws InvalidRouteException
*/
Expand Down
Loading