sabre/uri
Lightweight, RFC3986-compliant PHP URI utility library. Resolve relative URLs, normalize for comparisons, parse/build (like parse_url with Windows path edge cases), and split URIs into dirname/basename. Fully unit tested and inspired by Node’s URL APIs.
Installation:
composer require sabre/uri
Target 3.0.3 (PHP 7.4–8.5) for Laravel compatibility.
First Use Case: Resolve a relative URL against a base:
use Sabre\Uri\Uri;
$base = Uri::parse('https://example.com/base/');
$relative = Uri::resolve($base, 'subpath');
echo $relative; // Output: https://example.com/base/subpath
Key Entry Points:
Uri::parse(): Replace parse_url() for RFC3986 compliance (handles Windows paths, Unicode).Uri::resolve(): Join base + relative URLs (e.g., /api + users → /api/users).Uri::normalize(): Canonicalize URLs for comparison (e.g., /path// → /path/).Sabre\Uri\Uri class (static methods only; no instantiation needed).$base = Uri::parse('https://example.com/api/');
$resolved = Uri::resolve($base, '../users'); // Resolves to: https://example.com/users
/api/v1 + users).file:///C:/path (Windows) or s3://bucket/path (custom schemes).$url1 = Uri::parse('https://example.com/path//');
$url2 = Uri::parse('https://example.com/path');
$normalized1 = Uri::normalize($url1);
$normalized2 = Uri::normalize($url2);
assert($normalized1 === $normalized2); // True (both become `/path`)
$parsed = Uri::parse('https://user:pass@example.com:8080/path?query=1#frag');
$rebuilt = Uri::build($parsed);
assert($parsed['scheme'] === 'https');
Uri::parse() to extract query params or fragments before passing to Laravel’s Request or Url::to().$uri = Uri::parse('https://example.com/foo/bar/baz');
list($dirname, $basename) = Uri::split($uri);
// $dirname = 'https://example.com/foo/bar/'
// $basename = 'baz'
Route Generation:
Replace route('name') with Uri::resolve() for dynamic paths:
$base = Uri::parse(route('api.base'));
$userUrl = Uri::resolve($base, 'users/123');
Request Handling:
Parse incoming URLs with Uri::parse() to validate structure before Laravel’s Request processing:
$uri = Uri::parse(request()->getUri());
if ($uri['scheme'] !== 'https') {
abort(403, 'Insecure scheme');
}
File System Abstraction:
Normalize file:// URIs for cross-platform storage:
$path = Uri::normalize(Uri::parse('file:///C:/Users/Path With Spaces'));
API Clients:
Use Uri::resolve() to join API base URLs with endpoints:
$apiBase = Uri::parse(config('services.api.base_url'));
$endpoint = Uri::resolve($apiBase, 'v1/users');
Uri::parse() in bulk for URL validation (e.g., user-uploaded links).Uri::normalize() to compare URLs in tests:
$this->assertEquals(
Uri::normalize(Uri::parse('/path//')),
Uri::normalize(Uri::parse('/path'))
);
file:///C:/), Unicode (https://例子.测试), and relative URLs (../).Windows Path Handling:
file:///C:/path may parse differently across versions (see #81).$windowsUri = Uri::parse('file:///C:/Users/Path');
assert($windowsUri['host'] === ''); // Host is empty for Windows file URIs
Relative Resolution Quirks:
Uri::resolve() may not behave like browsers for certain edge cases (e.g., ./ or ../ in paths).$base = Uri::parse('https://example.com/');
$resolved = Uri::resolve($base, './relative');
// Output: https://example.com/relative (not https://example.com//relative)
Fragment Handling:
#hash) are preserved but may cause issues in build() if not handled.$uri = Uri::parse('https://example.com#hash');
if (isset($uri['fragment'])) {
// Handle fragment separately
}
Unicode Normalization:
https://例子.测试) may not normalize as expected.Uri::normalize() and verify with:
$normalized = Uri::normalize(Uri::parse('https://例子.测试'));
assert(strpos($normalized, '%E4') !== false); // Should be percent-encoded
Invalid URIs:
Uri::parse() throws Sabre\Uri\InvalidUriException for malformed inputs. Catch and log:
try {
Uri::parse('invalid:uri');
} catch (InvalidUriException $e) {
Log::error('Malformed URI', ['uri' => $e->getUri()]);
}
Unexpected Output:
var_export(Uri::parse($uri), true) to inspect parsed components.CI/CD Failures:
Custom Schemes:
Sabre\Uri\Uri by copying the class and overriding parse()/build() for non-standard schemes (e.g., s3://).Validation Rules:
use Sabre\Uri\Uri;
class ValidUri implements Rule
{
public function passes($attribute, $value)
{
try {
Uri::parse($value);
return true;
} catch (InvalidUriException) {
return false;
}
}
}
Performance Optimization:
Uri::parse() uses regex for scheme/host detection).config/uri.php or service provider needed.// app/Helpers/UriHelper.php
use Sabre\Uri\Uri;
if (!function_exists('uri_parse')) {
function uri_parse($uri) {
return Uri::parse($uri);
}
}
Uri::resolve() in route generation, clear route cache after changes:
php artisan route:
How can I help you explore Laravel packages today?