Skip to content

Commit 104672c

Browse files
committed
fix: match PHP $_REQUEST merge semantics in getRequestData()
Use array_replace_recursive() instead of array_merge() so numeric keys are preserved and array values are merged recursively, matching PHP's php_autoglobal_merge. Add tests for both behaviors, update the getVar() user guide docs, and add a changelog entry.
1 parent 983c2e3 commit 104672c

4 files changed

Lines changed: 31 additions & 6 deletions

File tree

‎system/Superglobals.php‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,12 @@ public function getRequestData(?string $requestOrder = null): array
417417

418418
foreach (str_split($requestOrder) as $type) {
419419
match ($type) {
420-
'G' => $request = array_merge($request, $this->get),
421-
'P' => $request = array_merge($request, $this->post),
422-
'C' => $request = array_merge($request, $this->cookie),
420+
// array_replace_recursive() matches PHP's own $_REQUEST merge
421+
// (php_autoglobal_merge): numeric keys are preserved and
422+
// array values are merged recursively.
423+
'G' => $request = array_replace_recursive($request, $this->get),
424+
'P' => $request = array_replace_recursive($request, $this->post),
425+
'C' => $request = array_replace_recursive($request, $this->cookie),
423426
default => null,
424427
};
425428
}

‎tests/system/SuperglobalsTest.php‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,25 @@ public function testGetRequestDataIgnoresUnknownOrderTypes(): void
359359
$this->assertSame(['get_key' => 'get_value'], $data);
360360
}
361361

362+
public function testGetRequestDataPreservesNumericKeys(): void
363+
{
364+
$this->superglobals->setGetArray([100 => 'foo']); // @phpstan-ignore argument.type (numeric keys are valid in superglobals, e.g. ?100=foo)
365+
366+
$data = $this->superglobals->getRequestData('G');
367+
368+
$this->assertSame([100 => 'foo'], $data);
369+
}
370+
371+
public function testGetRequestDataMergesRecursively(): void
372+
{
373+
$this->superglobals->setGetArray(['a' => ['x' => 'get']]);
374+
$this->superglobals->setPostArray(['a' => ['y' => 'post']]);
375+
376+
$data = $this->superglobals->getRequestData('GP');
377+
378+
$this->assertSame(['a' => ['x' => 'get', 'y' => 'post']], $data);
379+
}
380+
362381
// $_FILES tests
363382
public function testFilesGetArray(): void
364383
{

‎user_guide_src/source/changelogs/v4.7.5.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Bugs Fixed
6161
- **I18n:** Fixed a bug where ``Time::today()``, ``Time::yesterday()``, and ``Time::tomorrow()`` ignored the specified ``$timezone`` and ``setTestNow()`` when calculating the day.
6262
- **Logger:** Fixed a bug where interpolating a log message with array or non-stringable context values could raise PHP warnings or errors.
6363
- **Validation:** Fixed a bug where ``valid_cc_number`` accepted non-digit characters (e.g., a decimal point) in the card number. Such values could pass the Luhn check and triggered an ``Undefined array key`` warning inside it; the number is now checked with ``ctype_digit()``.
64+
- **IncomingRequest:** Fixed a bug where ``getVar()`` returned stale data after ``$_GET`` was updated during URI parsing. It now returns a merged view of ``$_GET``, ``$_POST``, and ``$_COOKIE`` (respecting the ``request_order`` ini setting) instead of reading the stale ``$_REQUEST``.
6465

6566
See the repo's
6667
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_

‎user_guide_src/source/incoming/incomingrequest.rst‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ getVar()
162162
in new projects. Even if you are already using it, we recommend that you use
163163
another, more appropriate method.
164164

165-
The ``getVar()`` method will pull from ``$_REQUEST``, so will return any data from ``$_GET``, ``$_POST``, or ``$_COOKIE`` (depending on php.ini `request-order <https://www.php.net/manual/en/ini.core.php#ini.request-order>`_).
165+
The ``getVar()`` method returns a merged view of ``$_GET``, ``$_POST``, and ``$_COOKIE`` (depending on php.ini `request-order <https://www.php.net/manual/en/ini.core.php#ini.request-order>`_). It does not read or modify ``$_REQUEST``.
166166

167167
.. warning:: If you want to validate POST data only, don't use ``getVar()``.
168168
Newer values override older values. POST values may be overridden by the
@@ -373,14 +373,16 @@ The methods provided by the parent classes that are available are:
373373
`Types of filters <https://www.php.net/manual/en/filters.php>`__.
374374
:param int $flags: Flags to apply. A list of flags can be found in
375375
`Filter flags <https://www.php.net/manual/en/filter.constants.php#filter.constants.flags.generic>`__.
376-
:returns: ``$_REQUEST`` if no parameters supplied, otherwise the REQUEST value if found, or null if not
376+
:returns: The merged ``$_GET``, ``$_POST``, and ``$_COOKIE`` data if no parameters supplied, otherwise the value if found, or null if not
377377
:rtype: array|bool|float|int|object|string|null
378378

379379
.. important:: This method exists only for backward compatibility. Do not use it
380380
in new projects. Even if you are already using it, we recommend that you use
381381
another, more appropriate method.
382382

383-
This method is identical to ``getGet()``, only it fetches REQUEST data.
383+
This method is identical to ``getGet()``, only it fetches the merged
384+
``$_GET``, ``$_POST``, and ``$_COOKIE`` data (respecting the
385+
``request_order`` ini setting) instead of ``$_REQUEST``.
384386

385387
.. php:method:: getGet([$index = null[, $filter = null[, $flags = null]]])
386388

0 commit comments

Comments
 (0)