---
layout: default
title: RFC3986 compliant URI Object API
description: The League URI object provides an expressive and efficient API around building and manipulating URI
---

URI Value Object
=======

The class 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::parse("./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(data: 'Héllo World!', mimetype: 'text/plain', parameters: 'charset=utf8');
echo $uri; // returns data:text/plain;charset=utf8,H%C3%A9llo%20World%21
~~~

The `parse` 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 a new instance cannot be returned, the method returns `null`.

~~~php
$uri = Uri::parse("invalid uri", "http://www.example.com/path/to/the/sky/");
var_dump($uri); // return null
~~~

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-info"><code>fromRfc8089</code> is added since version <code>7.4.0</code></p>
<p class="message-warning"><code>fromBaseUri</code> is deprecated since version <code>7.6.0</code> use <code>parse</code> instead</p>

## Validation

A `League\Uri\Contracts\UriException` exception is triggered if an invalid URI is given.

~~~php
$uri = Uri::new(':');
// throws a League\Uri\Exceptions\SyntaxError
// because the URI string is invalid
~~~

<p class="message-info">Because the <code>League\Uri\Exceptions\SyntaxError</code> exception extends <code>League\Uri\Contracts\UriException</code> you should catch any exception triggered by the package using the following code.</p>

~~~php
use League\Uri\Uri;
use League\Uri\Contracts\UriException;

try {
	$uri = Uri::new(':');
} catch (UriException $e) {
}
~~~

### RFC3986 Validation

By default, if the URI scheme is not recognized, the URI object will only validate [RFC3986](https://tools.ietf.org/html/rfc3986) rules. 
This means that depending on the URI scheme, the returned URI may not be valid.

~~~php
$uri = Uri::new('toto://thephpleague.com/path/to?here#content');
//this will not throw an error because this URI satified RFC3986 rules
~~~

<p class="message-notice">For extra validation rules to be triggered the URI must be absolute and the
scheme recognized. Otherwise, only basic RFC3986 rules are taken into account.</p>

### Scheme Validation

For the following URI schemes (order alphabetically) full validation is taken into account.

- data
- file
- ftp
- http(s)
- ws(s)
- blob **(since version 7.6)**
- mailto **(since version 7.6)**

### URN Validation

<p class="message-notice">Since version <code>7.6.0</code></p>

The generic URN validation based on [RFC8141](https://datatracker.ietf.org/doc/html/rfc8141) is used when encountering a URN scheme URI.
Because URN may expose more refined specification rules depending on their namespace identifier,
the validation rules applied can be considered as generic, and you may need more extra validation.
Please refer to the [URN object](/uri/7.0/urn/) for more information.

~~~php
$uri = Uri::new('urn://example.com'); 
// will throw a League\Uri\Exceptions\SyntaxError

$uri = Uri::new('urn:isbn:foobar/baz');
// will not throw but is an invalid isbn URN
// the ISBN namespace special string MUSR contain
// the ISBN-10 or ISBN-13 number
// possibly with hyphens only
~~~

### Component Validation

<p class="message-notice">Since version <code>7.6.0</code></p>

Based on the [IANA](https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml) URI scheme lists,
and on the different RFCs and specifications for each URI scheme, a validation based on URI
component presence is used. For instance, the following URI will be rejected.

```php
$uri = Uri::new('bitcoin:config/here');
//will work

$uri = Uri::new('bitcoin://thephpleague.com');
// will throw a League\Uri\Exceptions\SyntaxError
```

In the example, because a the `bitcoin` URI scheme cannot contain an authority component, an
exception is thrown. On the other hand, the path has not been checked to validate that it only
contained a valid bitcoin address. According to RFC3986, the path component is valid, but it is
not according to the [`bitcoin` specification](https://en.bitcoin.it/wiki/BIP_0021#Accessibility_(URI_scheme_name)).

The list of supported URI scheme can be found on the [UriScheme](https://github.com/thephpleague/uri-src/blob/master/uri/UriScheme.php) Enum
available since version `7.6`.

## Normalization

### Non-destructive 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>

### Destructive Normalization

<p class="message-notice">Available since version <code>7.6.0</code></p>

The `normalize` method applies extra normalization that may modify the original URI, those extra rules are:

- removing dot segments from the path
- normalizing the IPv6 and IPv4 host
- url-decode all non-reserved characters in the path and the query

```php
echo Uri::new('eXAMPLE://a/./b/../b/%63/%7bfoo%7d')->normalize()->toString();
// both calls display example://a/b/c/%7Bfoo%7D
```

## Resolution

<p class="message-notice">Available since version <code>7.6.0</code></p>

The `Uri::resolve` resolves a URI as a browser would for a relative URI while the `Uri::relativize`
does the opposite.

~~~php
$baseUri = Uri::new('http://www.ExaMPle.com');
$uri = 'http://www.example.com/?foo=toto#~typo';

$relativeUri = $baseUri->relativize($uri);
echo $relativeUri; // display "/?foo=toto#~typo
echo $baseUri->resolve($relativeUri);
echo $baseUri; // display 'http://www.example.com'
// display 'http://www.example.com/?foo=toto#~typo'
echo $baseUri->getUri()::class; //display \League\Uri\Uri
~~~

## Equivalence

Once normalized a URI can be compare using the two new comparison methods, `isSameDocument` and `equals` methods.

The two methods uses the normalized string representation of two URI to tell whether they are referencing the
same resource.

```php
use League\Uri\Uri;
use League\Uri\UriComparisonMode;

$uri = Uri::new('example://a/b/c/%7Bfoo%7D?foo=bar');
$uri->isSameDocument('eXAMPLE://a/./b/../b/%63/%7bfoo%7d?foo=bar'); // returns true
$uri->equals('eXAMPLE://a/./b/../b/%63/%7bfoo%7d?foo=bar'); // returns true
$uri->equals('eXAMPLE://a/./b/../b/%63/%7bfoo%7d?foo=bar#fragment', uriComparisonMode: UriComparisonMode::IncludeFragment); // returns false
```

In the last example the `equals` method took into account the URI `fragment` component. The `isSameDocument`
follow closely RFC3986 and never takes into account the URI `fragment` component.

## Builder

<p class="message-notice">Available since version <code>7.8.0</code></p>

While the `Uri` class can be used as a URI builder, the `Builder` class is introduced to provide
a convenient, fluent interface to creating a `Uri` instance. The `Builder` is particularly useful
when creating a `Uri` from scratch, without the constraint of starting from a valid `Uri` instance.
As a simple example the following is invalid using the `Uri` object:

```php
use League\Uri\Uri;

$uri = Uri::new()
    ->withPath("relative/path")
    ->withUserInfo("user", "pass")  // throws SyntaxError: The user info component must not be set if the host is not defined.
    ->withHost("example.com");
```

By contrast, when using the `Builder` class, full URI validation only occurs when `Builder::build()` is called.

```php
use League\Uri\Builder;

$uri = new Builder()
    ->path("relative/path")
    ->userInfo("user", "pass")
    ->host("example.com")
    ->build();

$uri::class;      // returns League\Uri\Uri
$uri->toString(); // returns "//user:pass@example.com/relative/path"
```

The `build()` method takes a single optional argument which is the `baseUri` that you can use to resolve
the URI. The base Uri can be any PHP native URI class, a PSR-7 compliant URI class, another `League\Uri\Uri`
instance or a string. If present, it must represent an absolute URI otherwise an exception will be
thrown.

```php
use League\Uri\Builder;

$uri = new Builder()
    ->host('uri.thephpleague.com')
    ->path('./.././uri')
    ->build('https://www.rfc-editor.org/rfc/rfc3986.html');

$uri::class;      // returns League\Uri\Uri
$uri->toString(); // returns "https://uri.thephpleague.com/uri"
```

The `Builder` constructor allows setting all URI components.

The last example can be rewritten as follows:

```php
use League\Uri\Builder;

$uri = new Builder(
        host: 'uri.thephpleague.com',
        path: './.././uri',
    )->build('https://www.rfc-editor.org/rfc/rfc3986.html');

$uri::class;      // returns League\Uri\Uri
$uri->toString(); // returns "https://uri.thephpleague.com/uri"
```

<p class="message-info">The <code>Builder</code> class is mutable and does not expose any getter methods.
Its sole purpose is to ease URI construction before producing an immutable <code>Uri</code> instance.</p>

At any given time, you can use the `reset()` method to reset an the `Builder` to its initial state.

```php
$builder = new Builder(host: 'uri.thephpleague.com', path: './.././uri');
$uri = $builder->build('https://www.rfc-editor.org/rfc/rfc3986.html');   
$uri->toString(); // returns "https://uri.thephpleague.com/uri"
$uriReset = $builder->reset()->build();
$uriReset->toString(); // returns ""
```

The `Builder` implements the `Conditionnable` interface to improve URI building using
conditional building methods.

```php
echo new Builder()
    ->path('path/to/whatever')
    ->when(
        0 === (random_int(0, 200) % 2), 
        fn (Builder $builder) => $builder->host('www.example.com'),
        fn (Builder $builder) => $builder->host('toto.com'),
    )
    ->scheme('https')
    ->build()
    ->toString();
// may return "https://www.example.com/path/to/whatever"   
//         or "https://toto.com/path/to/whatever" 
```

And also provides the `tap()` method to control side effects while building
your URI instance.

```php
echo new Builder()
    ->path('path/to/whatever')
    ->tap(function (Builder $builder): void {
        assert($builder->validate(), 'Builder is invalid');
    })
    ->scheme('https')
    ->build()
    ->toString();
// may return "https://www.example.com/path/to/whatever"   
//         or "https://toto.com/path/to/whatever" 
```

It also implements the `guard()` and `validate()` methods to ensure
the URI being constructed can be safely created when calling the `build()` method.

```php
new Builder()
    ->scheme('https')
    ->validate();
// return false if the URI can not be build
// a https URL needs at least a path and a host

echo new Builder()
        ->scheme('https')
        ->host('localhost')
        ->guard()
        ->query('foo=bar')
        ->build();
// throw an exception on failure
// or return the current instance 
// to allow validation without breaking chaining
```

## String Representations

The `Uri` class handles URI according to RFC3986 as such you can retrieve its string representation using the
`toString` method. 

```php
$uri = Uri::new("http://foo:bar@www.example.com:81/how/are/you?foo=baz#title");

echo $uri->toString(); //displays RFC3986 string representation
echo $uri;             //displays RFC3986 string representatio
```

But `Uri` can have multiple string representation depending on its scheme or context. As
such, the package provides several other string representations.

The `Uri` object also provides two complementary methods:

<p class="message-notice">Available since version <code>7.6.0</code></p>

`Uri:;toAsciiString()` and `Uri::toUnicodeString` to allow accessing the URI string
representation with the ascii host as per RFC3986 definition or using the host unicode
version if available using the `Uri::toUnicodeString`. the `toString()` method is an
alias to `toAsciiString()` method.

```php
$uri = Uri::new("http://BéBé.be:81/how/are/you?foo=baz#title");

echo $uri->toAsciiString();    //displays RFC3986 string representation "http://xn--bb-bjab.be:81/how/are/you?foo=baz#title"
echo $uri->toUnicodeString();  //displays RFC3987 string representation "http://bébé.be:81/how/are/you?foo=baz#title"
```

The `Uri` instance can be JSON encoded using the same URI representation from JavaScript to allow
easier interoperability

```php
$uri = Uri::new("http://foo:bar@www.example.com:81/how/are/you?foo=baz#title");
json_encode($uri); //returns "http:\/\/foo:bar@www.example.com:81\/how\/are\/you?foo=baz#title"
```

<p class="message-info">Available since version <code>7.6.0</code></p>

A new URI string representation is added, The `toDisplayString()` method returns a human-readable
representation of the URI, corresponding to its IRI form as defined in RFC 3987. Although
the resulting value may not constitute a syntactically valid URI, it is intended for
presentation purposes — for example, as the textual content of an HTML `<a>` element.

```php
$uri = Uri::new('eXAMPLE://a/./b/../b/%63/%7bfoo%7d?foo[]=bar');
echo $uri->toString();        //displays 'example://a/./b/../b/%63/%7bfoo%7d?foo%5B%5D=bar'
echo $uri->toDisplayString(); //displays 'example://a/./b/../b/c/{foo}?foo[]=bar'
````

For `file` scheme, specifics representations are added to allow representing Unix and Windows Path.

```php
$uri = Uri::new('file:///c:/windows/My%20Documents%20100%2520/foo.txt');
echo $uri->toWindowsPath(); //display 'c:\windows\My Documents 100%20\foo.txt'

$uri = Uri::new('file:///path%20empty/bar');
echo $uri->toUnixPath(); // display '/path empty/bar'

$uri = Uri::new('file://localhost/etc/fstab');
echo $uri->toRfc8089();    //display 'file:/etc/fstab'
```

<p class="message-notice">For any other scheme other than <code>file</code>, the method will return <code>null</code></p>

Last, but not least if you have a `Data URI` you can store the actual data into a file using the `toFileContents` method

```php
$uri = Uri::new('data:text/plain;charset=utf-8;base64,SGVsbG8gd29ybGQh');
$uri->toFileContents(destination: 'my/path/file.txt'); //returns the number of bytes stored

echo file_get_contents('my/path/file.txt'); //will return 'Hello world!'
```

<p class="message-notice">For any other scheme other than <code>data</code>, the method will return <code>null</code></p>

## Accessing Properties

Let's examine the result of building a URI:

~~~php
$uri = Uri::new("http://foo:bar@bébé.be: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 "xn--bb-bjab.be"
echo $uri->getUnicodeHost(); //displays "bébé.be"
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->getOrigin();      //displays "http://xn--bb-bjab.be:81"
$uri->getComponents(); 
// returns array {
//   "scheme" => "http",
//   "user" => "foo",
//   "pass" => "bar",
//   "host" => "xn--bb-bjab.be",
//   "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>

<p class="message-notice"><code>getUnicodeHost</code> is available since version <code>7.6.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.

<p class="message-notice"><code>getOrigin</code> is added in version <code>7.6.0</code></p>

The `getOrigin` method returns the URI origin used for comparison when calling the `isCrossOrigin` and `isSameOrigin` methods.
The algorithm used is defined by the [WHATWG URL Living standard](https://url.spec.whatwg.org/#origin)

~~~php
echo Uri::new('https://uri.thephpleague.com/uri/6.0/info/')->getOrigin(); //display 'https://uri.thephpleague.com';
echo Uri::new('blob:null/700475de-c453-11f0-8de9-0242ac120002')->getOrigin();               //display 'https://mozilla.org'
Uri::new('file:///usr/bin/php')->getOrigin();                     //returns null
Uri::new('data:text/plain,Bonjour%20le%20monde%21')->getOrigin(); //returns null
~~~

<p class="message-info">For absolute URI with the <code>file</code> scheme the method will return <code>null</code> (as this is left to the implementation decision)</p>
Because the origin property does not exist in the RFC3986 specification this additional steps is implemented:

- For non-absolute URI the method will return `null`

~~~php
Uri::new('/path/to/endpoint')->getOrigin(); //returns null
~~~

## Modifying 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
~~~

<p class="message-notice">The <code>when</code> method is available since version <code>7.6.0</code></p>
To ease building the instance, the `when` method is added to conditionally create your component.

<p class="message-notice">The <code>withUser</code>  and <code>withPassword</code> methods are available
since version <code>7.6.0</code> to be inline with PHP native <code>Uri</code> interface.</p>

```php
echo Uri::new('https://uri.thephpleague.com/components/7.0/modifiers/')
    ->when(
        fn (Uri $uri) => $uri->getPassword() !== null, 
        fn (Uri $uri) => $uri->withQuery('access=allowed'), //on true
        fn (Uri $uri) => $uri->withQuery('access=deny'),     //on false
    )
    ->toString();
// returns 'https://uri.thephpleague.com/components/7.0/modifiers/?access=deny';
```

If you want to apply more complex modification rules and want to re-use them on different
URI object you can use the `Uri::transform()` method. 

<p class="message-notice">The <code>transform()</code> method is available since version <code>7.8.0</code></p>

```php
$transformUri = function (Uri $uri): Uri {
    $query = parse_str(''.$uri->getQuery(), $parameters);
    unset($parameters['redirect']);
    if (!isset($parameters['filter'])) {
        $parameters['filter'] = [];
    }
    $parameters['filter']['verified'] = true;
    
    return $uri
        ->withQuery(http_build_query($parameters, encoding_type: PHP_QUERY_RFC3986))
        ->withFragment(null);
};

echo Uri::new($uriString)
    ->normalize()
    ->transform($transformUri)
    ->toString();
```

## URI Information

### URI Structure

The class also exposes a list of public methods which returns the URI structure.

`Uri::isAbsolute` tells whether the URI represents an absolute URI.

~~~php
Uri::fromServer($_SERVER)->isAbsolute(); //returns true
Uri::new("/🍣🍺")->isAbsolute(); //returns false
~~~

`Uri::isNetworkPath` tells whether the URI represents a network path URI.

~~~php
Uri::new("//example.com/toto")->isNetworkPath(); //returns true
Uri::new("/🍣🍺")->isNetworkPath(); //returns false
~~~

`Uri::isOpaque` tells whether the given URI object represents an opaque URI. An URI is said to be
opaque if and only if it is absolute but does not have an authority

~~~php
Uri::new("email:john@example.com?subject=🏳️‍🌈")->isOpaque(); //returns true
Uri::new("/🍣🍺")->isOpaque(); //returns false
~~~

`Uri::isAbsolutePath` tells whether the URI represents an absolute URI path.

~~~php
Uri::fromServer($_SERVER)->isAbsolutePath(); //returns false
Uri::new("/🍣🍺")->isAbsolutePath(); //returns true
~~~

`Uri::isRelativePath` tells whether the given URI object represents a relative path.

~~~php
Uri::new("🏳️‍🌈")->isRelativePath(); //returns true
Uri::new("/🍣🍺")->isRelativePath(); //returns false
~~~

`Uri::isCrossOrigin` and `Uri::isSameOrigin` tell whether two given URI objects
represent different origins. According to [RFC9110](https://www.rfc-editor.org/rfc/rfc9110#section-4.3.1) The "origin"
for a given URI is the triple of scheme, host, and port after normalizing
the scheme and host to lowercase and normalizing the port to remove
any leading zeros. The comparison is based on the return value of 
`Uri::getOrigin`.

~~~php
<?php
Uri::new('blob:http://xn--bb-bjab.be./700475de-c453-11f0-8de9-0242ac120002')
    ->isCrossOrigin('http://Bébé.BE./path'); // returns false

Uri::new('https://example.com/123')
    ->isSameOrigin('https://www.example.com/'); // returns false
~~~

The method takes into account i18n while comparing both URI if the PHP's `idn_*` functions can be used.

### URI Host Type

<p class="message-info">The following methods are available since version <code>7.7</code></p>

RFC3986 defines several type of host, the `Uri` class exposes the following
methods to help you get the host type:

- `Uri::isIpv4Host` tells whether the host represents an IPv4 host
- `Uri::isIpv6Host` tells whether the host represents an IPv6 host
- `Uri::isIpvFutureHost` tells whether the host represents an IPvFuture host
- `Uri::isRegisteredNameHost` tells whether the host represents a registered name host
- `Uri::isDomainHost`  tells whether the host represents an domain name host

<p class="message-info">Any Domain host is a registered name but not all
registered name are domain name</p>

```php
use League\Uri\Uri;
$urString = 'https://_uri.thephpleague.com'; // note the presence of the underscore!!
$uri = Uri::new($urString);
$uri->isRegisteredNameHost(); // returns true;
$uri->isDomainHost();         // returns false;
```

If the `Uri` host is a registered name, the class can be more precise with the `Uri::hasIDN` 
method which tells whether the given URI object contains a IDN host or not.

~~~php
Uri::new("https://bébé.be")->hasIdn(); //returns true
~~~
