spatie/url
Immutable URL parser/builder for PHP. Parse scheme, host, path and query, then fluently transform parts (withHost, withPath, withScheme) and manage query parameters. Supports allowed/sanitized schemes for safer URL handling.
Install via Composer:
composer require spatie/url
Start by parsing an existing URL or building a new one:
use Spatie\Url\Url;
// Parse from string
$url = Url::fromString('https://example.com/path?foo=bar#section');
// Build from components
$url = Url::fromParts([
'scheme' => 'https',
'host' => 'example.com',
'path' => '/path',
'query' => ['foo' => 'bar'],
'fragment' => 'section',
]);
First common use case: append query parameters to the current request URL.
$current = Url::fromString($_SERVER['REQUEST_URI'] ?? '');
$newUrl = $current->withQuery('next', '/dashboard');
with*() methods for immutable transformations.
$url = Url::fromString('https://example.com')
->withPath('/api/v1/users')
->withQuery('limit', 50)
->withoutQuery('offset');
$url = $url->withQuery(['foo' => 'bar', 'baz' => 'qux']); // replace all
// Or additive:
$url = $url->addQuery('foo', 'bar')->addQuery('foo', 'baz'); // foo=bar&foo=baz
$normalized = $url->withoutTrailingSlash()->normalizePath()->normalizeQuery();
// In a service provider
Url::macro('canonical', fn () => Url::fromString(url()->current())->withoutQuery('utm_*')->withoutFragment());
withQuery() return a new instance—forgetting to assign the result is a common source of bugs.addQuery() sequentially; withQuery(['a' => 1, 'b' => 2]) is deterministic, but array order can be surprising.Url::fromString() auto-decodes percent-encoded segments, but __toString() re-encodes safely—avoid manual concatenation to prevent double-encoding.withQuery('', 'value') adds a key with empty value (?=value), whereas omitting the key entirely requires withQuery([], ['key' => 'value']).__toString() or ->__toString() explicitly in headers—PHP may not auto-cast.Url::fromString() in your own subclass to inject custom parsing (e.g., for legacy systems with nonstandard URLs).How can I help you explore Laravel packages today?