URI
The simple implementation of PSR-7: Uri.
A URI taken apart into the pieces an application asks about: which scheme, which host, which path, what came after the question mark. Immutable, so handing one to something else cannot change the one you kept — every with…() gives back a copy.
The factory needs nothing to be built:
$factory = new UriFactory();A container can build it instead, and will fill the same two validators; neither way is the one you have to use.
Requirements
- PHP 8.1 or newer
Installation
composer require quillstack/uriUsage
Reading one apart
The factory asks for its validators, so the container builds it:
use Quillstack\DI\Container;
use Quillstack\Uri\Factory\UriFactory;
$factory = (new Container())->get(UriFactory::class);
$uri = $factory->createUri('https://user:secret@example.com:8443/users/42?page=2#top');
$uri->getScheme(); // 'https'
$uri->getHost(); // 'example.com'
$uri->getPort(); // 8443
$uri->getPath(); // '/users/42'
$uri->getQuery(); // 'page=2'
$uri->getFragment(); // 'top'
$uri->getUserInfo(); // 'user:secret'
$uri->getAuthority(); // 'user:secret@example.com:8443'
(string) $uri; // what went in, unchangedA port which is the usual one for the scheme is not part of the authority, because saying https://example.com:443 says nothing https://example.com does not:
$uri = $factory->createUri('https://example.com:443/x');
$uri->getPort(); // null
$uri->getAuthority(); // 'example.com'
(string) $uri; // https://example.com/xA URI which stops at the host
All of these are URIs, and all of them used to be refused outright:
$factory->createUri('https://example.org'); // path '/', nothing else
$factory->createUri('https://example.org?a=1'); // query 'a=1'
$factory->createUri('https://example.org#top'); // fragment 'top'The path ends at whichever of ? and # comes first, so a fragment written without a query is a fragment rather than the end of a directory name.
Changing one
Every change gives back a copy, so the one you were given stays as it was:
$next = $uri->withPath('/users/43')->withQuery('page=3');
(string) $uri; // https://example.com/users/42?page=2
(string) $next; // https://example.com/users/43?page=3Routing on the path
This is what quillstack/router dispatches on — the path rather than the whole thing, so a query string does not turn a known route into a 404:
$path = $request->getUri()->getPath();Technical documentation
Uri implements Psr\Http\Message\UriInterface in full: getScheme(), getAuthority(), getUserInfo(), getHost(), getPort(), getPath(), getQuery(), getFragment(), the matching with…() methods, and __toString().
| Constant | Value |
|---|---|
Uri::SCHEME_HTTP / Uri::SCHEME_HTTPS | http / https |
Uri::DEFAULT_PORT_HTTP / Uri::DEFAULT_PORT_HTTPS | 80 / 443 |
Uri::DEFAULT_PORTS | the two above, keyed by scheme |
UriFactory implements Psr\Http\Message\UriFactoryInterface; createUri() takes the string apart and validates it.
| Exception | Thrown when |
|---|---|
UnknownSchemeException | the scheme is not one this package knows |
UnknownHostException | the host is not a host |
Both extend UriException, and both implement the validation interface from quillstack/validator-interface.
Unit tests
composer testDocker
docker-compose up -d
docker exec -w /var/www/html -it quillstack_uri shLicense
MIT. See LICENSE.