byjg / uri
A PHP implementation of PSR-7 UriInterface with additional utility methods
6.0.0
2025-11-25 17:47 UTC
Requires
- php: >=8.3 <8.6
- psr/http-message: ^1.0|^1.1|^2.0
Requires (Dev)
- phpunit/phpunit: ^10.5|^11.5
- vimeo/psalm: ^5.9|^6.13
Suggests
None
Provides
Conflicts
None
Replaces
None
README
| sidebar_key | uri | ||
|---|---|---|---|
| tags |
|
PSR-7 URI Implementation
A PHP implementation of PSR-7 UriInterface with additional utility methods.
Features
- Implements PSR-7 UriInterface, with two deliberate differences for connection strings (see PSR-7 differences)
- Includes additional utility methods via CustomUriInterface
- Supports RFC3986 URI specification
- Type-safe implementation with PHP 8 attributes and strict typing
- Immutable class design pattern
PSR-7 differences
The URI is also used for connection strings (mysql://host:3306/db, h:9092), so two PSR-7 recommendations are not followed:
- The standard port is kept.
https://host:443keeps443ingetPort(),getAuthority()and the string (PSR-7 SHOULD return null and leave it out). - A URI without a scheme is written without
//.new Uri('h:9092')is read as hosthand port9092and written back ash:9092, not//h:9092. A URI with a scheme always has//after it, even without a host (sqlite:///tmp/db).
URI Encoding Behavior
PSR-7 requires URI compliant with RFC3986. This means the URI output will always be URL encoded. This applies to both creating a new instance and the string representation.
Examples:
// Creating a URI with special characters in the password $uri = \ByJG\Util\Uri::getInstance("https://user:pa&@host"); print((string)$uri); // Will print "https://user:pa%26@host" // Creating a URI with already encoded characters $uri = \ByJG\Util\Uri::getInstance("https://user:pa%26@host"); print((string)$uri); // Will print "https://user:pa%26@host" // Using withUserInfo with unencoded password $uri = \ByJG\Util\Uri::getInstance("https://host") ->withUserInfo("user", "pa&"); print((string)$uri); // Will print "https://user:pa%26@host" // Using withUserInfo with already encoded password $uri = \ByJG\Util\Uri::getInstance("https://host") ->withUserInfo("user", "pa%26"); print((string)$uri); // Will print "https://user:pa%2526@host" // The username is decoded by getUsername() and encoded in the string form, like the password $uri = \ByJG\Util\Uri::getInstance("https://email@host.com:pass@host"); print($uri->getUsername()); // Will print "email@host.com" print((string)$uri); // Will print "https://email%40host.com:pass@host"
Additional Methods
This implementation extends PSR-7 UriInterface with the following additional methods through \ByJG\Util\CustomUriInterface:
| Method | Description |
|---|---|
getUsername(): ?string |
Get the decoded username of the URI |
getPassword(): ?string |
Get the decoded password of the URI |
getQueryPart(string $key): ?string |
Get a specific query parameter by key |
getQueryParts(string $key): array |
Get every value of a query parameter |
withQueryKeyValue(string $key, string $value, bool $isEncoded = false): self |
Add or update a query parameter |
hasQueryKey(string $key): bool |
Check if a query parameter exists |
Static Factory Methods
The class provides convenient static factory methods:
// Create from string $uri = Uri::getInstance("https://example.com/path?query=value#fragment"); // Create from another UriInterface $uri2 = Uri::getInstance($uri);
Documentation
Installation
composer require "byjg/uri"
Running Tests
vendor/bin/phpunit