RFC3986 URI
The League\Uri\Uri
class implements:
- League’s own UriInterface contracts
- PHP’s JsonSerializable interfaces.
The class handles all URI schemes and default to RFC3986 rules if the scheme is not present and not recognized as special.
Instantiation
The League\Uri\Uri
class comes with the following named constructors to ease instantiation.
Using a string
<?php
use League\Uri\Uri;
$uri = Uri::createFromString(
'http://example.com/path/to?q=foo%20bar#section-42'
);
Using Uri components
use League\Uri\Uri;
use League\Uri\UriString;
$uri = Uri::createFromComponents(
UriString::parse("http://uri.thephpleague/5.0/uri/api")
);
Using environment variables
//don't forget to provide the $_SERVER array
$uri = Uri::createFromServer($_SERVER);
Using a base URI
Resolves an URI as a browser would for a relative URI.
$uri = Uri::createFromBaseUri(
"./p#~toto",
"http://www.example.com/path/to/the/sky/"
);
echo $uri; //displays "http://www.example.com/path/to/the/sky/p#~toto"
This method expect at most two variables. The URL to resolve and the base URL to use for resolution. If not base URL is provided, the URL to resolve must be absolute. On the other hand, if a base URL is provided it must be absolute.
Using an URI object
use Zend\Diactoros\Uri as ZendUri;
use League\Uri\Uri;
$zendUri = new ZendUri("http://www.example.com/path/to/the/sky");
$zendUri->getQuery(); //return '';
$leagueUri = Uri::createFromUri($zendUri);
$leagueUri->getQuery(); //return null;
This named constructor accepts PSR-7 or League UriInterface implementing objects as its sole argument.
Using the content of a file
Returns a new URI object with the data
scheme and using the content of the file located at the provided path. Because the function uses internally PHP’s file streaming capabilities an optional context resource can be used to better access the file content.
$uri = Uri::createFromDataPath('path/to/my/png/image.png');
echo $uri; //returns 'data:image/png;charset=binary;base64,...'
//where '...' represent the base64 representation of the file
Using a Windows file path
Returns a new URI object using the file
scheme for a Windows file path.
$uri = Uri::createFromWindowsPath('c:\windows\My Documents\my word.docx');
echo $uri; //returns 'file://localhost/c:My%20Documents/my%20word.docx'
Using a Unix file path
Returns a new URI object using the file
scheme for a Unix file path.
$uri = Uri::createFromUnixPath('/path/to/my/file.xml');
echo $uri; //returns 'file://localhost/path/to/my/file.xml'
URI validation
A League\Uri\Contracts\UriException
exception is triggered if an invalid URI is given.
$uri = Uri::createFromString(':');
// throws a League\Uri\Exceptions\SyntaxError
// because the URI string is invalid
use League\Uri\Uri;
use League\Uri\Contracts\UriException;
try {
$uri = Uri::createFromString(':');
} catch (UriException $e) {
}
Basic validations
By default, if the URI scheme is not recognized, the URI object wil only validate RFC3986 rules. This means that depending on the URI scheme the returned URI may not be valid.
$mailto_uri = 'mailto://thephpleague.com/path/to?here#content';
$uri = Uri::createFromString($mailto_uri);
//this will not throw an error because this URI satified RFC3986 rules
For the following special schemes (order alphabetically) extra validation are take into account.
- data
- file
- ftp
- http(s)
- ws(s)
These extra validation rules are triggerd only when the URI is absolute and the scheme is detected. Otherwise only basic RFC3986 rules are taken into account.
http(s) scheme validation
Authority presence
If a scheme is present and the scheme specific part of a Http URI is not empty the URI can not contain an empty authority. Thus, some Http URI modifications must be applied in a specific order to preserve the URI validation.
$uri = Uri::createFromString('http://uri.thephpleague.com/');
echo $uri->withHost(null)->withScheme(null);
// will throw an League\Uri\Exceptions\SyntaxError
// you can not remove the Host if a scheme is present
Instead you are required to proceed as below
$uri = Uri::createFromString('http://uri.thephpleague.com/');
echo $uri->withScheme(null)->withHost(null); //displays "/"
Path validity
According to RFC3986, if an HTTP URI contains a non empty authority part, the URI path must be the empty string or absolute. Thus, some modification may trigger an SyntaxError
.
$uri = Uri::createFromString('http://uri.thephpleague.com/');
echo $uri->withPath('uri/schemes/http');
// will throw an League\Uri\Exceptions\SyntaxError
Instead you are required to submit an absolute path
$uri = Uri::createFromString('http://uri.thephpleague.com/');
echo $uri->withPath('/uri/schemes/http');
// displays 'http://uri.thephpleague.com/uri/schemes/http'
Of course this does not mean that rootless path are forbidden, the following code is fine.
$uri = Uri::createFromString('?foo=bar');
echo $uri->withPath('uri/schemes/http'); // displays 'uri/schemes/http?foo=bar'
ftp scheme validation
It can not contains a query and or a fragment component.
$uri = Uri::createFromString('ftp://thephpleague.com/path/to/image.png;type=i');
$uri->withQuery('p=1'); // will throw an League\Uri\Exceptions\SyntaxError
ws(s) scheme validation
It can not contain a fragment component as per RFC6455.
$uri = Uri::createFromString('wss://thephpleague.com/path/to?here#content');
// will throw an League\Uri\Exceptions\SyntaxError
data scheme validation
Even though all URI properties are defined and accessible attempt to set any component other than the path will result in the object throwing a SyntaxError
exception. As adding data to theses URI parts will generate an invalid Data URI.
$uri = Uri::createFromPath('path/to/my/png/image.png');
$uri->getHost(); //returns null
$uri->withHost('example.com'); // will throw an League\Uri\Exceptions\SyntaxError
Accessing URI properties
The RFC3986 URI object exposes the following methods.
public function Uri::__toString(): string
public function Uri::getScheme(void): ?string
public function Uri::getUserInfo(void): ?string
public function Uri::getHost(void): ?string
public function Uri::getPort(void): ?int
public function Uri::getAuthority(void): ?string
public function Uri::getPath(void): string
public function Uri::getQuery(void): ?string
public function Uri::getFragment(void): ?string
public function Uri::jsonSerialize(void): string
You can access the URI string, its individual parts and components using their respective getter methods. This lead to the following result for a simple HTTP URI:
$uri = Uri::createFromString("http://foo:bar@www.example.com:81/how/are/you?foo=baz#title");
echo $uri->getScheme(); //displays "http"
echo $uri->getUserInfo(); //displays "foo:bar"
echo $uri->getHost(); //displays "www.example.com"
echo $uri->getPort(); //displays 81 as an integer
echo $uri->getAuthority(); //displays "foo:bar@www.example.com:81"
echo $uri->getPath(); //displays "/how/are/you"
echo $uri->getQuery(); //displays "foo=baz"
echo $uri->getFragment(); //displays "title"
echo $uri;
//displays "http://foo:bar@www.example.com:81/how/are/you?foo=baz#title"
echo json_encode($uri);
//displays "http:\/\/foo:bar@www.example.com:81\/how\/are\/you?foo=baz#title"
Modifying URI properties
To replace one of the URI component you can use the modifying methods exposed by all URI object. If the modifications do not alter the current object, it is returned as is, otherwise, a new modified object is returned.
<?php
public function Uri::withScheme(?string $scheme): self
public function Uri::withUserInfo(?string $user [, ?string $password = null]): self
public function Uri::withHost(?string $host): self
public function Uri::withPort(?int $port): self
public function Uri::withPath(string $path): self
public function Uri::withQuery(?string $query): self
public function Uri::withFragment(?string $fragment): self
Since all URI objects are immutable you can chain each modifying methods to simplify URI creation and/or modification.
$uri = Uri::createFromString("ws://thephpleague.com/fr/")
->withScheme("wss")
->withUserInfo("foo", "bar")
->withHost("www.example.com")
->withPort(81)
->withPath("/how/are/you")
->withQuery("foo=baz");
echo $uri; //displays wss://foo:bar@www.example.com:81/how/are/you?foo=baz
URI normalization
Out of the box the package normalizes any given URI according to the non destructive rules of RFC3986.
These non destructives rules are:
- scheme and host components are lowercased;
- the host is converted to its ascii representation using punycode if needed
- query, path, fragment components are URI encoded if needed;
- the port number is removed from the URI string representation if the standard port is used;
$uri = Uri::createFromString(
"hTTp://www.ExAmPLE.com:80/hello/./wor ld?who=f 3#title"
);
echo $uri; //displays http://www.example.com/hello/./wor%20ld?who=f%203#title
$uri = Uri::createFromComponent(parse_url("hTTp://www.bébé.be?#"));
echo $uri; //displays http://xn--bb-bjab.be?#