Skip to content
PHP News
Search
Accepted PHP 8.6

Followup Improvements for ext/uri

Adds URI builder classes, URI and host type detection, and component-aware percent-encoding functions to the ext/uri classes.

Add URI building support as outlined in the RFC?

Primary vote

21 Yes 0 No 2 abstain 100% approval

This poll has closed.

Add support for detecting URI type as outlined in the RFC?

  • No 0
  • Yes 18
  • Abstain 2

This poll has closed.

Add support for host type detection as outlined in the RFC?

  • No 0
  • Yes 17
  • Abstain 1

This poll has closed.

Add support for percent-encoding as outlined in the RFC?

  • No 0
  • Yes 15
  • Abstain 6

This poll has closed.

Each part had its own vote and needed a two-thirds majority. All four passed without a single vote against:

  • URI building passed 21 to 0, with 2 abstaining.
  • URI type detection passed 18 to 0, with 2 abstaining.
  • Host type detection passed 17 to 0, with 1 abstaining.
  • Percent-encoding passed 15 to 0, with 6 abstaining.

Voting closed on May 19, 2026, and the target is PHP 8.6.

Summary

PHP's URI extension gives you the Uri\Rfc3986\Uri and Uri\WhatWg\Url classes. This RFC from Máté Kocsis adds the pieces that were left out of the first version, in four parts: a way to build a URI from scratch, a way to check what kind of URI you have, a way to check what kind of host it has, and proper percent-encoding.

Building a URI

Today you can only modify a URI that already exists. Each with method returns a new object, so three changes create three objects. The order can matter too, since some changes throw if another component is missing.

$uri2 = $uri1
    ->withScheme("https")
    ->withHost("example.net")
    ->withPath("/foo/bar"); // This creates 3 objects altogether!

The RFC adds builder classes. You set the components you want, then call build(), and the URI object is only created at the end.

$uri = new Uri\Rfc3986\UriBuilder()
    ->setScheme("https")
    ->setHost("example.com")
    ->setPath("/foo/bar")
    ->build();

There's a matching Uri\WhatWg\UrlBuilder. Each setter validates its own input right away, while checks that need the whole URI wait until build(). A reset() method clears the builder so you can reuse it.

Checking what you have

Uri\Rfc3986\Uri gets a getUriType() method that tells you whether a URI is absolute or a relative reference, like /foo or //host.com/foo. Uri\WhatWg\Url gets isSpecialScheme(), which returns true for special schemes such as http, https and file.

Both classes also get getHostType(). It tells you whether the host is an IPv4 address, an IPv6 address, a registered name, and so on, and it returns null when there's no host.

Percent-encoding

Which characters need encoding depends on the part of the URI. rawurlencode() doesn't know that, so it turns every / into %2F, even inside a path. The RFC adds Uri\Rfc3986\uri_percent_encode() and Uri\WhatWg\url_percent_encode(), which take a mode saying which component you're encoding.

Uri\Rfc3986\uri_percent_encode("/foo/bar/[baz]", Uri\Rfc3986\UriPercentEncodingMode::Path);
// /foo/bar/%5Bbaz%5D

There's no matching decode function. The RFC says decoding can change what a query means.

What it means for existing code

Nothing breaks. The RFC only adds new classes, enums, methods and functions, and because the URI classes are final, no userland code extends them.