Examples
Practical examples demonstrating common use cases.
Building URIs from Scratch
use ByJG\Util\Uri;
$uri = Uri::getInstance()
->withScheme("https")
->withHost("api.example.com")
->withPort(443)
->withPath("/v1/users")
->withQueryKeyValue("page", "1")
->withQueryKeyValue("limit", "20");
echo (string)$uri;
// "https://api.example.com:443/v1/users?page=1&limit=20"
Database Connection Strings
MySQL
$uri = Uri::getInstance("mysql://root:password@localhost:3306/mydb");
echo $uri->getScheme(); // "mysql"
echo $uri->getUsername(); // "root"
echo $uri->getPassword(); // "password"
echo $uri->getHost(); // "localhost"
echo $uri->getPort(); // 3306
echo $uri->getPath(); // "/mydb"
PostgreSQL with Query Parameters
$uri = Uri::getInstance("postgresql://user:pass@host/database")
->withQueryKeyValue("sslmode", "require")
->withQueryKeyValue("connect_timeout", "10");
echo (string)$uri;
// "postgresql://user:pass@host/database?sslmode=require&connect_timeout=10"
SQLite
// Windows path
$uri = Uri::getInstance("sqlite://C:\\data\\mydb.sqlite");
// Unix path
$uri = Uri::getInstance("sqlite:///var/lib/data/mydb.sqlite");
Modifying Existing URIs
$uri = Uri::getInstance("http://example.com/old-path?old=param");
// Change to HTTPS
$uri = $uri->withScheme("https");
// Change path
$uri = $uri->withPath("/new-path");
// Replace query string entirely
$uri = $uri->withQuery("new=param&another=value");
echo (string)$uri;
// "https://example.com/new-path?new=param&another=value"
Working with Query Parameters
Adding Parameters
$uri = Uri::getInstance("https://api.example.com/search");
$uri = $uri
->withQueryKeyValue("q", "search term")
->withQueryKeyValue("category", "books")
->withQueryKeyValue("sort", "price");
echo (string)$uri;
// "https://api.example.com/search?q=search%20term&category=books&sort=price"
Reading Parameters
$uri = Uri::getInstance("https://example.com?name=John&age=30&active");
echo $uri->getQueryPart("name"); // "John"
echo $uri->getQueryPart("age"); // "30"
var_dump($uri->hasQueryKey("active")); // true
var_dump($uri->getQueryPart("active")); // "" (empty string, key exists)
var_dump($uri->getQueryPart("missing")); // NULL
Updating Parameters
$uri = Uri::getInstance("https://example.com?page=1&limit=10");
// Update existing parameter
$uri = $uri->withQueryKeyValue("page", "2");
echo $uri->getQuery(); // "page=2&limit=10"
Handling Special Characters
Email as Username
echo $uri->getPassword(); // "password"
echo $uri->getHost(); // "ftp.server.com"
// The "@" in the user is percent-encoded on output
Special Characters in Password
// Automatically encoded during parsing
echo $uri->getUserInfo(); // "user:p%40ss%26word%21"
echo $uri->getPassword(); // "p@ss&word!" (decoded internally)
File URIs
Local File Path
// Unix
$uri = Uri::getInstance("file:///home/user/documents/file.txt");
echo $uri->getPath(); // "/home/user/documents/file.txt"
// Windows
$uri = Uri::getInstance("file://C:\\Users\\John\\file.txt");
echo $uri->getPath(); // "C:\\Users\\John\\file.txt"
IPv6 hosts
An IPv6 literal is written in brackets, as RFC 3986 requires, so that the colons inside are
not read as the port separator. getHost() returns the literal with its brackets, which
is what getAuthority() and __toString() need to reassemble it:
$uri = Uri::getInstance("kafka://[::1]:9092");
echo $uri->getHost(); // "[::1]"
echo $uri->getPort(); // 9092
echo $uri->getAuthority(); // "[::1]:9092"
// with userinfo, and a zone identifier (RFC 6874)
Uri::getInstance("https://user:pw@[2001:db8::1]:443/p")->getHost(); // "[2001:db8::1]"
Uri::getInstance("kafka://[fe80::1%25eth0]:9092")->getHost(); // "[fe80::1%25eth0]"
The brackets are matched for their shape, not validated as an address -- just as a registered
name is not validated as a hostname. Checking that an address is well formed belongs to
whatever consumes the host. IPvFuture ([v7.foo]) is not supported.
Drive letters and one-character hosts
A Windows drive letter and a one-character host with a port look alike: C: and h:. They
are told apart by what follows the colon -- digits mean a port, anything else means a
drive letter:
Uri::getInstance("C:\\Windows\\file.db")->getPath(); // "C:\\Windows\\file.db" -- a path
Uri::getInstance("C:foo")->getPath(); // "C:foo" -- a path
Uri::getInstance("kafka://h:9092")->getHost(); // "h", port 9092 -- a host
C:1 is genuinely ambiguous -- it is both a drive-relative path and a one-character host on
port 1, and nothing in the string separates them. It is read as host C on port 1.
Write C:\\1 or C:/1 if a path is meant.
API URL Building
$baseUri = Uri::getInstance("https://api.github.com");
// Build endpoint URL
$uri = $baseUri
->withPath("/repos/byjg/php-uri/issues")
->withQueryKeyValue("state", "open")
->withQueryKeyValue("labels", "bug")
->withQueryKeyValue("per_page", "50");
echo (string)$uri;
// "https://api.github.com/repos/byjg/php-uri/issues?state=open&labels=bug&per_page=50"
Parsing and Extracting Information
$uri = Uri::getInstance($url);
// Extract all components
$components = [
'scheme' => $uri->getScheme(), // "https"
'user' => $uri->getUsername(), // "john"
'pass' => $uri->getPassword(), // "secret"
'host' => $uri->getHost(), // "example.com"
'port' => $uri->getPort(), // 8080
'path' => $uri->getPath(), // "/path/to/resource"
'query' => $uri->getQuery(), // "search=test&filter=active"
'fragment' => $uri->getFragment(), // "section"
];
print_r($components);
Immutability Example
$original = Uri::getInstance("https://example.com/path");
// Each modification returns a new instance
$modified1 = $original->withPath("/new-path");
$modified2 = $original->withScheme("http");
echo $original->getPath(); // "/path" (unchanged)
echo $original->getScheme(); // "https" (unchanged)
echo $modified1->getPath(); // "/new-path"
echo $modified2->getScheme(); // "http"
Type Conversion
// From another PSR-7 implementation
$psr7Uri = new \GuzzleHttp\Psr7\Uri("https://example.com");
$uri = Uri::getInstance($psr7Uri);
// Back to string
$uriString = (string)$uri;
// Re-parse
$newUri = Uri::getInstance($uriString);