The League of Extraordinary Packages

Our Packages:

Presented by The League of Extraordinary Packages

Getting Started

Uri parser

Uri schemes

Uri manipulations

Uri components

Upgrading Guide

URI middlewares

Definition

An URI middleware is a class which provides a convenient mechanism for filtering and manipulating an URI object. The only hard requirement is that a URI middleware MUST returns an URI instance of the same type that the one it received.

Example

For instance here’s how you would update the query string from a given URI object:

<?php

use Slim\Http\Uri as SlimUri;

$base_uri = "http://www.example.com?fo.o=toto#~typo";
$query_to_merge = 'fo.o=bar&taz=';

$uri = SlimUri::createFromString($base_uri);
$source_query = $uri->getQuery();
parse_str($source_query, $params);
parse_str($query_to_merge, $new_params);
$new_query = http_build_query(
    array_merge($params, $new_params),
    '',
    '&',
    PHP_QUERY_RFC3986
);

$new_uri = $uri->withQuery($new_query);
echo $new_uri; // display http://www.example.com?fo_o=bar&taz=#~typo

Using the provided League\Uri\Modifiers\MergeQuery middleware the code becomes

<?php

use League\Uri\Modifiers\MergeQuery;
use Slim\Http\Uri as SlimUri;

$base_uri = "http://www.example.com?fo.o=toto#~typo";
$query_to_merge = 'fo.o=bar&taz=';

$uri = SlimUri::createFromString($base_uri);
$modifier = new MergeQuery($query_to_merge);

$new_uri = $modifier->process($uri);
echo $new_uri;
// display http://www.example.com?fo.o=bar&taz=#~typo
// $new_uri is a SlimUri object

In addition to merging the query to the URI, MergeQuery has:

URI Middleware Interface

<?php

public UriMiddlewareInterface::process($uri);

The UriMiddlewareInterface::process :

To reduce BC break, all implemented URI middlewares still support the __invoke method. The method is an alias of the process method.

<?php

use League\Uri\Modifiers\MergeQuery;
use Slim\Http\Uri as SlimUri;

$uri = SlimUri::createFromString("http://www.example.com?fo.o=toto#~typo");
$new_uri = (new MergeQuery('fo.o=bar&taz='))($uri);
echo $new_uri; // display http://www.example.com?fo.o=bar&taz=#~typo
               // $new_uri is a SlimUri object

Converting a callable into a Uri Middleware is easy with the CallableAdapter class. This class takes a callable as its unique argument and adapt its usage to the UriMiddlewareInterface interface.

<?php

use League\Uri\Modifiers\CallableAdapter;
use Slim\Http\Uri as SlimUri;

$callable = function ($uri) {
    return $uri->withHost('thephpleague.com');
};

$uri = SlimUri::createFromString("http://www.example.com?fo.o=toto#~typo");
$new_uri = (new CallableAdapter($callable))->process($uri);
echo $new_uri; // display http://thephpleague.com?fo.o=toto#~typo
               // $new_uri is a SlimUri object

Middlewares which manipulate several URI components

Resolving a relative URI

The Resolve URI Middleware provides the mean for resolving an URI as a browser would for a relative URI. When performing URI resolution the returned URI is normalized according to RFC3986 rules. The uri to resolved must be another Uri object.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\Resolve;

$baseUri     = Http::createFromString("http://www.example.com/path/to/the/sky/");
$relativeUri = Http::createFromString("./p#~toto");
$modifier    = new Resolve($baseUri);
$newUri = $modifier->process($relativeUri);
echo $newUri; //displays "http://www.example.com/path/to/the/sky/p#~toto"

Relativize an URI

The Relativize URI Middleware provides the mean to construct a relative URI that when resolved against the same URI yields the same given URI. This modifier does the inverse of the Resolve modifier. The uri to relativize must be another Uri object.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\Relativize;
use League\Uri\Modifiers\Resolve;

$baseUri = Http::createFromString('http://www.example.com');
$relativizer = new Relativize($baseUri);
$resolver = new Resolve($baseUri);
$uri = Http::createFromString('http://www.example.com/?foo=toto#~typo');
$relativeUri = $relativizer->process($uri);
echo $relativeUri; // display "/?foo=toto#~typo
echo $resolver->process($relativeUri); // display 'http://www.example.com/?foo=toto#~typo'

URI comparison

To help with URI objects comparison, the League\Uri\Modifiers\Normalize URI Middleware is introduce to normalize URI according to the following rules:

If you normalized two URI objects it become easier to compare them to determine if they are representing the same resource:

<?php

use League\Uri\Modifiers\Normalize;
use League\Uri\Schemes\Http;

$uri = Http::createFromString("http://스타벅스코리아.com/to/the/sky/");
$altUri = Http::createFromString("http://xn--oy2b35ckwhba574atvuzkc.com/path/../to/the/./sky/");
$modifier = new Normalize();

$newUri    = $modifier->process($uri);
$newAltUri = $modifier->process($altUri);

var_dump($newUri->__toString() === $newAltUri->__toString()); //return true

You should avoid using the Normalize URI middleware for anything else but URI comparison as some changes applied may introduce some data loss.

Applying multiple URI middleware to a single URI

Since all URI middleware returns a URI object instance it is possible to chain them together. To ease this chaining the package comes bundle with the League\Uri\Modifiers\Pipeline class. The class uses the pipeline pattern to modify the URI by passing the results from one modifier to the next one.

The League\Uri\Modifiers\Pipeline uses the Pipeline::pipe to attach a URI Middleware following the First In First Out rule.

<?php

use League\Uri\Modifiers\HostToAscii;
use League\Uri\Modifiers\KsortQuery;
use League\Uri\Modifiers\Pipeline;
use League\Uri\Modifiers\RemoveDotSegments;
use League\Uri\Schemes\Http;
use Slim\Http\Uri;

$origUri = Uri::createFromString("http://스타벅스코리아.com/to/the/sky/");
$origUri2 = Http::createFromString("http://xn--oy2b35ckwhba574atvuzkc.com/path/../to/the/./sky/");

$modifier = (new Pipeline())
    ->pipe(new RemoveDotSegment())
    ->pipe(new HostToAscii())
    ->pipe(new KsortQuery());

$origUri1Alt = $modifier->process($origUri1);
$origUri2Alt = $modifier->process($origUri2);

echo $origUri1Alt; //display http://xn--oy2b35ckwhba574atvuzkc.com/to/the/sky/
echo $origUri2Alt; //display http://xn--oy2b35ckwhba574atvuzkc.com/to/the/sky/

The League\Uri\Modifiers\Pipeline is a URI middleware as well which can lead to advance modifications from you URI in a sane an normalized way.

This class is heavily influenced by the League\Pipeline package.

Query specific URI Middlewares

In addition to modifiying the URI query component, the middleware normalizes the query string to RFC3986

Sorting the query keys

Sorts the query according to its key values.

Using PHP sorting constant

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\KsortQuery;

$uri = Http::createFromString("http://example.com/test.php?kingkong=toto&foo=bar+baz#doc3");
$modifier = new KsortQuery(SORT_REGULAR);
$newUri = $modifier->process($uri);
echo $newUri; //display "http://example.com/test.php?foo=bar%20baz&kingkong=toto#doc3"

Using a user defined comparison function like the uksort function

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\KsortQuery;

$sort = function ($value1, $value2) {
    return strcasecmp($value1, $value2);
};

$modifier = new KsortQuery($sort);

$uri = Http::createFromString("http://example.com/test.php?kingkong=toto&foo=bar+baz#doc3");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://example.com/test.php?foo=bar%20baz&kingkong=toto#doc3"

Merging query string

Merges a submitted query string to the URI object to be modified

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\MergeQuery;

$uri = Http::createFromString("http://example.com/test.php?kingkong=toto&foo=bar+baz#doc3");
$modifier = new MergeQuery('kingkong=godzilla&toto');
$newUri = $modifier->process($uri);
echo $newUri; //display "http://example.com/test.php?kingkong=godzilla&foo=bar%20baz&toto#doc3"

Append data to the query string

Append a submitted query string to the URI object to be modified.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\AppendQuery;

$uri = Http::createFromString("http://example.com/test.php?kingkong=toto&foo=bar+baz#doc3");
$modifier = new AppendQuery('kingkong=godzilla&toto');
$newUri = $modifier->process($uri);
echo $newUri; //display "http://example.com/test.php?kingkong=toto&kingkong=godzilla&foo=bar%20baz&toto#doc3"

Removing query pairs

Removes query pairs from the current URI query string by providing the pairs key.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveQueryKeys;

$uri = Http::createFromString("http://example.com/test.php?kingkong=toto&foo=bar+baz#doc3");
$modifier = new RemoveQueryKeys(["foo"]);
$newUri = $modifier->process($uri);
echo $newUri; //display "http://example.com/test.php?kingkong=toto#doc3"

Path specific URI Middlewares

In addition to modifiying the URI path component, the middleware normalizes the path encoding to RFC3986.

Removing dot segments

Removes dot segments according to RFC3986:

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveDotSegments;

$uri = Http::createFromString("http://www.example.com/path/../to/the/./sky/");
$modifier = new RemoveDotSegments();
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/to/the/sky/"

Removing empty segments

Removes adjacent separators with empty segment.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveEmptySegments;

$uri = Http::createFromString("http://www.example.com/path//to/the//sky/");
$modifier = new RemoveEmptySegments();
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path/to/the/sky/"

Removing trailing slash

Removes the path trailing slash if present

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveTrailingSlash;

$uri = Http::createFromString("http://www.example.com/path/?foo=bar");
$modifier = new RemoveTrailingSlash();
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path?foo=bar"

Adding trailing slash

Adds the path trailing slash if not present

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\AddTrailingSlash;

$uri = Http::createFromString("http://www.example.com/sky#top");
$modifier = new AddTrailingSlash();
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/sky/#top"

Removing leading slash

Removes the path leading slash if present.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveLeadingSlash;

$uri = Http::createFromString("/path/to/the/sky/");
$modifier = new RemoveLeadingSlash();
$newUri = $modifier->process($uri);
echo $newUri; //display "path/to/the/sky"

Adding leading slash

Adds the path leading slash if not present.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\AddLeadingSlash;

$uri = Http::createFromString("path/to/the/sky/");
$modifier = new AddLeadingSlash();
$newUri = $modifier->process($uri);
echo $newUri; //display "/path/to/the/sky"

Updating path dirname

Adds, update and or remove the path dirname from the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\Dirname;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky");
$modifier = new Dirname("/road/to");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/road/to/sky"

Updating path basename

Adds, update and or remove the path basename from the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\Basename;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky");
$modifier = new Basename("paradise.xml");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path/to/the/paradise.xml"

Updating path extension

Adds, update and or remove the path extension from the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\Extension;

$uri = Http::createFromString("http://www.example.com/export.html");
$modifier = new Extension("csv");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/export.csv"

Add the path basepath

Adds the path basepath from the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\AddBasePath;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky");
$modifier = new AddBasePath("/the/real");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/the/real/path/to/the/sky"

Remove the path basepath

Removes the path basepath from the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveBasePath;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky");
$modifier = new RemoveBasePath("/path/to/the");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/sky"

Appending path

Appends a path to the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\AppendSegment;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new AppendSegment("and/above");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path/to/the/sky/and/above"

Prepending segments

Prepends a path to the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\PrependSegment;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new PrependSegment("and/above");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/and/above/path/to/the/sky/and/above"

Replacing a path segment

Replaces a segment from the current URI path with a new path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\ReplaceSegment;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new ReplaceSegment(3, "sea");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path/to/the/sea/"

This URI middleware supports negative offset

The previous example can be rewritten using negative offset:

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\ReplaceSegment;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new ReplaceSegment(-1, "sea");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path/to/the/sea"

Removing selected segments

Removes selected segments from the current URI path by providing the segments offset.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveSegments;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new RemoveSegments([1, 3]);
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path/the/"

This URI middleware supports negative offset

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveSegments;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new RemoveSegments([-1, -2]);
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com/path/the"

Update Data URI parameters

Update Data URI parameters

<?php

use League\Uri\Schemes\Data as DataUri;
use League\Uri\Modifiers\DataUriParameters;

$uriString = "data:text/plain;charset=US-ASCII,Hello%20World!";
$uri = DataUri::createFromString($uriString);
$modifier = new DataUriParameters("charset=utf-8");
$newUri = $modifier->process($uri);
echo $newUri; //display "data:text/plain;charset=utf-8,Hello%20World!"

Transcoding Data URI from ASCII to Binary

Transcoding a data URI path from text to its base64 encoded version

<?php

use League\Uri\Schemes\Data as DataUri;
use League\Uri\Modifiers\DataUriToBinary;

$uriString = "data:text/plain;charset=US-ASCII,Hello%20World!";
$uri = DataUri::createFromString($uriString);
$modifier = new DataUriToBinary();
$newUri = $modifier->process($uri);
echo $newUri; //display "data:text/plain;charset=US-ASCII;base64,SGVsbG8gV29ybGQh"

Transcoding Data URI from Binary to ascii

Transcoding a data URI path from text to its base64 encoded version

<?php

use League\Uri\Schemes\Data as DataUri;
use League\Uri\Modifiers\DataUriToAscii;

$uriString = "data:text/plain;charset=US-ASCII;base64,SGVsbG8gV29ybGQh";
$uri = DataUri::createFromString($uriString);
$modifier = new DataUriToAscii();
$newUri = $modifier->process($uri);
echo $newUri; //display "data:text/plain;charset=US-ASCII,Hello%20World!"

Host specific URI Middlewares

In addition to modifiying the URI host component, the middleware normalizes the host content.

Transcoding the host to ascii

Transcodes the host into its ascii representation according to RFC3986:

<?php

use GuzzleHttp\Psr7\Uri;
use League\Uri\Modifiers\HostToAscii;

$uri = new Uri("http://스타벅스코리아.com/to/the/sky/");
$modifier = new HostToAscii();
$newUri = $modifier->process($uri);
echo get_class($newUri); //display \GuzzleHttp\Psr7\Uri
echo $newUri; //display "http://xn--oy2b35ckwhba574atvuzkc.com/to/the/sky/"

This middleware will have no effect on League URI objects as this conversion is done by default.

Transcoding the host to its IDN form

Transcodes the host into its idn representation according to RFC3986:

<?php

use GuzzleHttp\Psr7\Uri;
use League\Uri\Modifiers\HostToUnicode;

$uriString = "http://xn--oy2b35ckwhba574atvuzkc.com/to/the/./sky/";
$uri = new Uri($uriString);
$modifier = new HostToUnicode();
$newUri = $modifier->process($uri);
echo get_class($newUri); //display \GuzzleHttp\Psr7\Uri
echo $newUri; //display "http://스타벅스코리아.com/to/the/sky/"

This middleware will have no effect on League URI objects because the object always transcode the host component into its RFC3986/ascii representation.

Removing Zone Identifier

Removes the host zone identifier if present

<?php

use Zend\Diactoros\Uri;
use League\Uri\Modifiers\RemoveZoneIdentifier;

$uriString = 'http://[fe80::1234%25eth0-1]/path/to/the/sky.php';
$uri = new Uri($uriString);
$modifier = new RemoveZoneIdentifier();
$newUri = $modifier->process($uri);
echo get_class($newUri); //display \Zend\Diactoros\Uri
echo $newUri; //display 'http://[fe80::1234]/path/to/the/sky.php'

Adding the root label

Adds the root label if not present

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\AddRootLabel;

$uriString = 'http://example.com:83';
$uri = Http::createFromString($uriString);
$modifier = new AddRootLabel();
$newUri = $modifier->process($uri);
echo $newUri; //display 'http://example.com.:83'

Removing the root label

Removes the root label if present

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveRootLabel;

$uriString = 'http://example.com.#yes';
$uri = Http::createFromString($uriString);
$modifier = new RemoveRootLabel();
$newUri = $modifier->process($uri);
echo $newUri; //display 'http://example.com#yes'

Appending labels

Appends a host to the current URI host.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\AppendLabel;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new AppendLabel("fr");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://www.example.com.fr/path/to/the/sky/"

Prepending labels

Prepends a host to the current URI path.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\PrependLabel;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new PrependLabel("shop");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://shop.www.example.com/path/to/the/sky/and/above"

Replacing host label

Replaces a label from the current URI host with a host.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\ReplaceLabel;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new ReplaceLabel(2, "admin.shop");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://admin.shop.example.com/path/to/the/sky"

The host is considered as a hierarchical component, labels are indexed from right to left according to host RFC

This URI middleware supports negative offset

The previous example can be rewritten using negative offset:

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\ReplaceLabel;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new ReplaceLabel(-1, "admin.shop");
$newUri = $modifier->process($uri);
echo $newUri; //display "http://admin.shop.example.com/path/to/the/sky"

Removing selected labels

Removes selected labels from the current URI host. Labels are indicated using an array containing the labels offsets.

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveLabels;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new RemoveLabels([2]);
$newUri = $modifier->process($uri);
echo $newUri; //display "http://example.com/path/the/sky/"

The host is considered as a hierarchical component, labels are indexed from right to left according to host RFC

This URI middleware supports negative offset

The previous example can be rewritten using negative offset:

<?php

use League\Uri\Schemes\Http;
use League\Uri\Modifiers\RemoveLabels;

$uri = Http::createFromString("http://www.example.com/path/to/the/sky/");
$modifier = new RemoveLabels([-1]);
$newUri = $modifier->process($uri);
echo $newUri; //display "http://example.com/path/the/sky/"