diff --git a/src/adapter/ServerRequestAdapter.php b/src/adapter/ServerRequestAdapter.php index 90bd2752..6c4a81c8 100644 --- a/src/adapter/ServerRequestAdapter.php +++ b/src/adapter/ServerRequestAdapter.php @@ -48,6 +48,13 @@ */ final class ServerRequestAdapter { + /** + * Query parameters resolved from the PSR-7 ServerRequestInterface. + * + * @phpstan-var array + */ + private array $queryParams = []; + /** * Creates a new instance of the {@see ServerRequestAdapter} class. * @@ -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; @@ -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 + * @return array Query parameters as an associative array. + * + * @phpstan-return array * * Usage example: * ```php @@ -235,6 +244,10 @@ public function getParsedBody(): array|object|null */ public function getQueryParams(): array { + if ($this->queryParams !== []) { + return $this->queryParams; + } + return $this->psrRequest->getQueryParams(); } @@ -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())); diff --git a/tests/TestCase.php b/tests/TestCase.php index 0bf0284d..18dc0df0 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -149,6 +149,7 @@ protected function statelessApplication(array $config = []): StatelessApplicatio 'enableStrictParsing' => false, 'enablePrettyUrl' => true, 'rules' => [ + 'site/query/' => 'site/query', 'site/update/' => 'site/update', ], ], diff --git a/tests/http/StatelessApplicationTest.php b/tests/http/StatelessApplicationTest.php index f7808a51..a37bdf0d 100644 --- a/tests/http/StatelessApplicationTest.php +++ b/tests/http/StatelessApplicationTest.php @@ -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. */ diff --git a/tests/support/stub/SiteController.php b/tests/support/stub/SiteController.php index 1a3ddb2b..70994ffc 100644 --- a/tests/support/stub/SiteController.php +++ b/tests/support/stub/SiteController.php @@ -231,6 +231,20 @@ public function actionPost(): mixed return $this->request->post(); } + /** + * @phpstan-return array + */ + 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 */