PHP RFC: ext/uri followups
- Version: 0.1
- Date: 2025-10-17
- Author: Máté Kocsis, kocsismate@php.net
- Status: Draft
- Target version: PHP 8.5
- Implementation: https://github.com/kocsismate/php-src/pull/9
Introduction
This RFC proposes a follow-up to the URL Parsing API RFC, extending the URI
and URL
classes with additional capabilities for constructing, analyzing, and manipulating URIs.
The goal is to provide a more complete and developer-friendly API for URI handling, consistent with both the WHATWG URL Standard and RFC 3986.
Proposal
The following new functionality is introduced in this proposal:
- URI builder
- Query string manipulation
- Retrieving/modifying path segments as an array
- Retrieving the host type
- Determining if the URL is “special” (per WHATWG)
- Dedicated percent-encoding/decoding support
URI Builder
A fluent API is introduced for programmatically constructing and modifying URIs:
$uri = (new UriBuilder()) ->scheme('https') ->host('example.com') ->path('/foo/bar') ->query(['a' => 1, 'b' => 2]) ->fragment('section1') ->build(); echo $uri; // "https://example.com/foo/bar?a=1&b=2#section1"
This builder makes URI creation and modification easier and less error-prone than manually concatenating strings or repeatedly invoking Uri::with*()
methods.
Design goals:
- Immutable
Uri
objects as the result - Chainable fluent syntax
- Automatic percent-encoding of each component
- Validation of scheme, host, and port consistency
Query String Manipulation
Uri
and Url
classes now expose getQueryParams()
/ setQueryParams()
methods for working directly with parsed query parameters:
$uri = new Uri('https://example.com/?foo=bar&x=1'); $params = $uri->getQueryParams(); $params['y'] = '2'; $uri = $uri->withQueryParams($params); echo $uri->getQuery(); // "foo=bar&x=1&y=2"
A dedicated UriQuery
helper object also offers a structured interface similar to JavaScript’s URLSearchParams
.
Path Segments as an Array
getPathSegments()
and withPathSegments()
provide convenient access to the path component as an array:
$uri = new Uri('https://example.com/foo/bar/baz'); $segments = $uri->getPathSegments(); // ['foo', 'bar', 'baz'] $uri = $uri->withPathSegments(['a', 'b']); echo $uri->getPath(); // "/a/b"
This is useful for frameworks and routers that manipulate paths dynamically.
Host Type Detection
The new getHostType()
method returns the type of the host component:
$uri = new Uri('https://192.168.0.1/'); echo $uri->getHostType(); // UriHostType::IPv4 $uri = new Uri('https://[2001:db8::1]/'); echo $uri->getHostType(); // UriHostType::IPv6 $uri = new Uri('https://example.com/'); echo $uri->getHostType(); // UriHostType::Domain
Possible return values include:
UriHostType::Domain
UriHostType::IPv4
UriHostType::IPv6
UriHostType::Opaque
UriHostType::None
Determining if a URL is Special
The WHATWG URL Standard defines *special* schemes (http
, https
, ftp
, file
, ws
, wss
), which have distinct parsing and serialization rules.
The new isSpecial()
method allows checking this:
$url = new Url('https://example.com'); var_dump($url->isSpecial()); // true $url = new Url('custom:example'); var_dump($url->isSpecial()); // false
This enables low-level control for applications that need to mirror WHATWG behaviors in parsing or normalization.
Percent-Encoding and Decoding
Dedicated static methods provide precise control over percent-encoding and decoding according to RFC 3986 rules:
Uri::encodeComponent('a b'); // "a%20b" Uri::decodeComponent('a%20b'); // "a b"
These utilities respect the character sets defined in RFC 3986 and may later be extended to support application/x-www-form-urlencoded
semantics as used in HTML forms.
Backward Incompatible Changes
None.
All APIs are additive and live in the Uri
/ Url
namespaces without changing existing behavior.
Proposed PHP Version(s)
PHP 8.6
RFC Impact
To the Ecosystem
What effect will the RFC have on IDEs, Language Servers (LSPs), Static Analyzers, Auto-Formatters, Linters and commonly used userland PHP libraries?
To Existing Extensions
Will existing extensions be affected?
To SAPIs
Describe the impact to CLI, Development web server, embedded PHP etc.
Open Issues
Make sure there are no open issues when the vote starts!
Future Scope
This section should outline areas that you are not planning to work on in the scope of this RFC, but that might be iterated upon in the future by yourself or another contributor.
This helps with long-term planning and ensuring this RFC does not prevent future work.
Voting Choices
Patches and Tests
Implementation
After the RFC is implemented, this section should contain:
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
References
Links to external references, discussions, or RFCs.
Rejected Features
Keep this updated with features that were discussed on the mail lists.
Changelog
If there are major changes to the initial proposal, please include a short summary with a date or a link to the mailing list announcement here, as not everyone has access to the wikis' version history.