PHP 8.5 adds a URI extension to the standard library. It provides two immutable classes, Uri\Rfc3986\Uri and Uri\WhatWg\Url, with no extra package required. The RFC 3986 implementation uses uriparser. The WHATWG implementation uses the Lexbor engine that also powers PHP 8.4's DOM API.

uri-example.php
<?php
use Uri\Rfc3986\Uri;

$uri = new Uri('https://shop.example/catalog/electronics?page=2&brand=acme#reviews');

echo $uri->getScheme();
echo $uri->getHost();
echo $uri->getPath();
echo $uri->getQuery();
echo $uri->getFragment();

The extension addresses long-standing limits in parse_url(), which has existed since PHP 4. That function returns an associative array with input-dependent keys, performs no URL validation, and does not include reconstruction logic. Malformed or untrusted input can produce unexpected results. The new classes create typed objects and validate their input during parsing.

The two classes represent different standards. Uri\Rfc3986\Uri is intended for general URI syntax, including URNs, custom schemes and relative references. Uri\WhatWg\Url follows the browser-oriented WHATWG model for web links. Without a base URL, it expects an absolute URL. Its API handles the Unicode and ASCII forms of internationalized hostnames and can serialize a hostname as Punycode through toAsciiString().

A URN such as urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 fits the RFC 3986 class. A web address such as https://exämple.com/path?query=1 can be processed by the WHATWG class. The RFC implementation exposes normalized components through methods such as getScheme(), getHost(), getPath(), getQuery() and getFragment(). It also has raw accessors including getRawUserInfo(), getRawUsername(), getRawHost() and getRawPath(). Both APIs expose authentication details, while the WHATWG API provides getAsciiHost() and getUsername() among its URL-specific accessors.

Constructors report invalid input through dedicated exceptions. RFC 3986 failures can raise Uri\UriException or Uri\InvalidUriException. WHATWG construction can raise Uri\WhatWg\InvalidUrlException. Static parsing offers a non-throwing path. Uri\Rfc3986\Uri::parse() returns an object or null. Uri\WhatWg\Url::parse() can also fill a supplied errors array with UrlValidationError objects, allowing applications to inspect validation failures such as invalid form input.

Both classes use immutable wither methods. Calls such as withScheme(), withPath(), withQuery(), withPort() and withFragment() return new objects, leaving the original value unchanged. The APIs also provide toString(), toRawString() and toAsciiString() for serialization. Uri\WhatWg\Url::equals() and the corresponding RFC 3986 method compare normalized URI values. UriComparisonMode::IncludeFragment controls whether a fragment participates in that comparison.

PHP recommends the new classes for new code and migration work where compatibility with parse_url() behavior is not required. Applications that validate a URL with one parser and later retrieve it with another can create security risks. The URI extension gives PHP applications a common, standards-based foundation for parsing, validation, comparison and modification.