Skip to content

WireInput::url() throws "array offset on false" / null-to-explode deprecation when REQUEST_URI begins with // #2270

@adrianbj

Description

@adrianbj

Short description of the issue

When $input->url() is called early in a request (before the matched page is available) and $_SERVER['REQUEST_URI'] begins with a double slash (e.g. the homepage requested as //), PHP emits a warning and a deprecation notice from WireInput::url().

Expected behavior

$input->url() should return a sanitized URL string without emitting warnings, regardless of how many leading/trailing slashes are in the request URI.

Actual behavior

Two messages are emitted (on PHP 8.x):

Warning: Trying to access array offset on false in
.../wire/core/WireInput/WireInput.php on line 1013

Deprecated: explode(): Passing null to parameter #2 ($string) of type string is deprecated in
.../wire/core/WireInput/WireInput.php on line 1013

Root cause: In the else if(isset($_SERVER['REQUEST_URI'])) branch of WireInput::url():

$info = parse_url($_SERVER['REQUEST_URI']);
$parts = explode('/', $info['path']);

parse_url('//') returns false (a leading // is parsed as a protocol-relative URL with an empty host, which PHP treats as malformed). Accessing $info['path'] on false raises "Trying to access array offset on false" and evaluates to null, which is then passed to explode(), raising the deprecation notice.

A related edge case: parse_url('//foo') returns an array with a host key but no path key, so $info['path'] is also unsafe there (undefined index).

Optional: Suggestion for a possible fix

Guard the path access so both cases ($info === false, or no path key) fall back to an empty string:

} else if(isset($_SERVER['REQUEST_URI'])) {
    // page not yet available, attempt to pull URL from request uri
    $info = parse_url($_SERVER['REQUEST_URI']);
    $path = is_array($info) && isset($info['path']) ? $info['path'] : '';
    $parts = explode('/', $path);
    $charset = $config ? $config->pageNameCharset : '';
    foreach($parts as $i => $part) {
        if($i > 0) $url .= "/";
        $url .= ($charset === 'UTF8' ? $sanitizer->pageNameUTF8($part) : $sanitizer->pageName($part, false));
    }
    if(strlen($path) && substr($path, -1) == '/') {
        $url = rtrim($url, '/') . '/'; // trailing slash
    }
}

Steps to reproduce the issue

  1. Load any ProcessWire site's homepage with two trailing slashes, e.g. https://example.com//
  2. Observe the warning/deprecation notice emitted from WireInput::url() (visible with display_errors on / in logs on PHP 8.x).

Setup/Environment

  • ProcessWire version: 3.0.263 (dev) — present in current core
  • PHP version: 8.x (warning/deprecation surface on PHP 8.0+)
  • MySQL version: n/a
  • Any 3rd party modules related: none

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions