codeigniter4 / codeigniter4/CodeIgniter4

Bug: `getVar()` behaves inconsistently with GET parameters

Đang mở
#9,872 6 bình luận 2 reaction 0 người được giao Xem trên GitHub
bug
Ngôn ngữ chính
PHP
Star
6k
Fork
2k
Merge trung bình
1 ngày 11 giờ
Pull request đã merge (30 ngày)
73

Mô tả

### PHP Version

8.4

### CodeIgniter4 Version

4.6.4

### CodeIgniter4 Installation Method

Composer (using `codeigniter4/appstarter`)

### Which operating systems have you tested for this bug?

macOS

### Which server did you use?

cli-server (PHP built-in webserver)

### Environment

development

### Database

-

### What happened?

In some cases, using `$validator->withRequest()` will not work correctly. Let's consider this test:

https://github.com/codeigniter4/CodeIgniter4/blob/11f0130a5ecc447d5a4c21b2ba991ea381433949/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php#L226-L241

As you may notice in the above test, `SiteURIFactory` updates some superglobals, here:

https://github.com/codeigniter4/CodeIgniter4/blob/11f0130a5ecc447d5a4c21b2ba991ea381433949/system/HTTP/SiteURIFactory.php#L162-L175

The problem is that while `$_SERVER['QUERY_STRING']` and `$_GET` are being updated, the `$_REQUEST` isn't. And `$_REQUEST` is needed to make `getVar()` work correctly.

https://github.com/codeigniter4/CodeIgniter4/blob/11f0130a5ecc447d5a4c21b2ba991ea381433949/system/Validation/Validation.php#L505-L527

https://github.com/codeigniter4/CodeIgniter4/blob/11f0130a5ecc447d5a4c21b2ba991ea381433949/system/HTTP/IncomingRequest.php#L496-L506

### Steps to Reproduce

```php
public function testQueryStringWithQueryStringAndRequest(): void
{
// /index.php?/ci/woot?code=good#pos
$_SERVER['REQUEST_URI'] = '/index.php?/ci/woot?code=good';
$_SERVER['QUERY_STRING'] = '/ci/woot?code=good';
$_SERVER['SCRIPT_NAME'] = '/index.php';

// these are always the same at the beginning
$_GET['/ci/woot?code'] = 'good';
$_REQUEST['/ci/woot?code'] = 'good';

$factory = $this->createSiteURIFactory($_SERVER);

$expected = 'ci/woot';
$this->assertSame($expected, $factory->detectRoutePath('QUERY_STRING'));
$this->assertSame('code=good', $_SERVER['QUERY_STRING']);
$this->assertSame(['code' => 'good'], $_GET);
// this will fail
$this->assertSame(['code' => 'good'], $_REQUEST);
}
```

### Expected Output

Validation method `$validator->withRequest()` should work correctly.

The most tempting solution is to add `syncRequestAfterGetChange()` to `Superglobals` and call it from `SiteURIFactory` whenever `$_GET` is modified. This would keep `$_REQUEST` synchronized with current values.

The downside is it introduces "magic" behavior that violates standard PHP semantics where `$_REQUEST` is populated once and never auto-updated. However, since we update `$_GET` as a "standard", behavior, then updating `$_REQUEST` may be acceptable?

I was thinking about something like this:

```php
public function syncRequestAfterGetChange(): void
{
$requestOrder = ini_get('request_order') ?: ini_get('variables_order');

$this->request = [];

foreach (str_split($requestOrder) as $type) {
match ($type) {
'G' => $this->request = array_merge($this->request, $this->get),
'P' => $this->request = array_merge($this->request, $this->post),
'C' => $this->request = array_merge($this->request, $this->cookie),
default => null,
};
}

$_REQUEST = $this->request;
}
```

But I'm unsure if this is the right direction.

### Anything else?

https://forum.codeigniter.com/showthread.php?tid=93652

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.