---
layout: default
title: RFC3986 compliant URI Object API
---

URI Value Object
=======

The package provides an expressive and efficient API around building and manipulating URI. It allows
the easy creation of URI in multiple contexts to increase your DX while working with URI.

<p class="message-notice">The class handles all URI schemes and default to
<a href="https://tools.ietf.org/html/rfc3986">RFC3986</a> rules if the scheme is not present and not
recognized as special.</p>

## Instantiation

While the default constructor is private and can not be accessed to instantiate a new object,
the `League\Uri\Uri` class comes with the different named constructors to ease instantiation.

~~~php
<?php

use League\Uri\Uri;
use League\Uri\UriString;
use Laminas\Diactoros\Uri as LaminasUri;

// using a string or an object which expose the `__toString` method

$uri = Uri::new('http://example.com/path/to?q=foo%20bar#section-42');
$uri->toString(); // display 'http://example.com/path/to?q=foo%20bar#section-4'

$laminasUri = new LaminasUri("http://www.example.com/path/to/the/sky");
$laminasUri->getQuery(); //return '';

Uri::new($laminasUri)->getQuery(); //return null;

// using `parse_url` or the package `UriString::parse` static method.

$uri = Uri::fromComponents(UriString::parse("http://uri.thephpleague/7.0/uri/api"));

//don't forget to provide the $_SERVER array
$uri = Uri::fromServer($_SERVER);
~~~

<p class="message-warning">If you supply your own hash to <code>fromComponents</code>,
you are responsible for providing well parsed components without their URI delimiters.</p>

<p class="message-warning">The <code>fromServer</code> method only relies on the server's 
safe parameters to determine the current URI. If you are using the library behind a 
proxy the result may differ from your expectation as no <code>$_SERVER['HTTP_X_*']</code>
header is taken into account for security reasons.</p>

You can also return a URI based on standard specifications:

~~~php
$uri = Uri::fromBaseUri("./p#~toto", "http://www.example.com/path/to/the/sky/");
echo $uri; //displays "http://www.example.com/path/to/the/sky/p#~toto"

$template = 'https://example.com/hotels/{hotel}/bookings/{booking}';
$variables = ['booking' => '42', 'hotel' => 'Rest & Relax'];
echo Uri::fromTemplate($template, $variables)->toString();
//displays "https://example.com/hotels/Rest%20%26%20Relax/bookings/42"

$uri = Uri::fromFileContents('path/to/my/png/image.png');
echo $uri; //returns 'data:image/png;charset=binary;base64,...'
//where '...' represent the base64 representation of the file

$uri = Uri::fromData('Héllo World!', 'text/plain', 'charset=utf8');
echo $uri; // returns data:text/plain;charset=utf8,H%C3%A9llo%20World%21
~~~

The `fromBaseUri` method resolves URI using the same logic behind URL construction
in a browser and [is inline with how the Javascript](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) `URL` object constructor works.
If no base URI is provided, the URI to resolve **MUST** be absolute. Otherwise, the base URI **MUST** be absolute.

The `fromTemplate` method resolves a URI using the rules and variable from the 
[URITemplate specification RFC6570](http://tools.ietf.org/html/rfc6570):
The method expects at most two parameters. The URI template to resolve and the variables use
for resolution. You can get a more in-depth understanding of
[URI Template](/uri/7.0/uri-template) in its dedicated section of the documentation.

The `fromFileContents`
named constructor generates a [Data URI](https://datatracker.ietf.org/doc/html/rfc2397)
following its RFC specification. with the provided file location, the method will
base64 encode the content of the file and return the generated URI.

The `fromData`
named constructor generates a [Data URI](https://datatracker.ietf.org/doc/html/rfc2397)
following its RFC specification. with the provided data and an optional mimetype and parameters.

Last but not least, you can easily translate RFC8089, Windows, Unix paths to URI using the three (3)
following methods.

~~~php
$uri = Uri::fromWindowsPath('c:\windows\My Documents\my word.docx');
echo $uri; //returns 'file://localhost/c:My%20Documents/my%20word.docx'

$uri = Uri::fromUnixPath('/path/to/my/file.xml');
echo $uri; //returns 'file://localhost/path/to/my/file.xml'

$uri = Uri::fromRfc8089('file:/etc/fstab');
echo $uri = //returns 'file:///etc/fstab'
~~~

<p class="message-notice"><code>fromRfc8089</code> is added since version <code>7.4.0</code></p>

Accessing URI properties
-------

Let's examine the result of building a URI:

~~~php
$uri = Uri::new("http://foo:bar@www.example.com:81/how/are/you?foo=baz#title");
echo $uri->getScheme();    //displays "http"
echo $uri->getUsername();  //displays "foo"
echo $uri->getPassword();  //displays "bar"
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->toString();
//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"
$uri->getComponents(); 
// returns array {
//   "scheme" => "http",
//   "user" => "foo",
//   "pass" => "bar",
//   "host" => "www.example.com",
//   "port" => 81,
//   "path" => "/how/are/you",
//   "query" => "foo=baz",
//   "fragment" => "title",
// }
~~~

<p class="message-info">Apart from the path component, which is always a string, all the other URI components can be
<code>null</code></p>

<p class="message-notice"><code>getUsername</code> and <code>getPassword</code> are added in version <code>7.5.0</code></p>

The returned value for each URI component is kept encoded. If you need the decoded value you should use the
[league/uri-component](/components) to extract and manipulate each individual component.

Modifying URI properties
-------

Use the modifying methods exposed by all URI instances to replace one of the URI component.
If the modifications do not alter the current object, it is returned as is, otherwise,
a new modified object is returned.

<p class="message-notice">Any modification method can trigger a
<code>League\Uri\Contracts\UriException</code> exception if the resulting URI is not
valid. Just like with the instantiation methods, validation is scheme dependant.</p>

<p class="message-info">Apart from the path component, which is always a string, to delete
a URI component you need to specify its content as being <code>null</code></p>

Since all URI objects are immutable you can chain each modifying methods to simplify URI
creation and/or modification.

~~~php
$uri = Uri::new("ftp://thephpleague.com/fr/")
    ->withScheme("yolo")
    ->withUserInfo("foo", "bar")
    ->withHost("www.example.com")
    ->withPort(81)
    ->withPath("")
    ->withQuery("foo=baz")
    ->withFragment('fine');

echo $uri; //displays yolo://foo:bar@www.example.com:81?foo=baz#fine
~~~

URI normalization
-------

Out of the box the package normalizes any given URI according to the non-destructive rules
of [RFC3986](https://tools.ietf.org/html/rfc3986).

These non-destructive rules are:

- scheme and host components are lowercase;
- 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;

~~~php
$uri = Uri::new("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::fromComponent(parse_url("hTTp://www.bébé.be?#"));
echo $uri; //displays http://xn--bb-bjab.be?#
~~~

<p class="message-info">The last example depends on the presence of the <code>idn_to_*</code> functions, otherwise the code will trigger a <code>MissingFeature</code> exception</p>
