atldays/laravel-url is a Laravel package for working with URLs in a more predictable, framework-friendly way.
At its core, the package builds on top of spatie/url, adds Laravel integration, supports browser-specific schemes, provides sanitizer pipelines for unsafe input, ships validation rules, request macros, and optional integration with spatie/laravel-data.
Working with URLs in real applications is usually messier than simply parsing a clean string.
Inputs may come from:
Origin and Refererchrome-extension://...This package gives you a single Laravel-oriented layer for those cases while still relying on the excellent parsing foundation provided by spatie/url.
Atldays\Url\Url value object built on top of spatie/urlchrome-extension, moz-extension, chrome, opera, edgespatie/laravel-data casts and transformer^8.2^11.0|^12.0|^13.0Install the package:
composer require atldays/laravel-url
If you want to customize sanitizer profiles, publish the config:
php artisan vendor:publish --tag="url-config"
If you want to use spatie/laravel-data integration, install it separately:
composer require spatie/laravel-data
use Atldays\Url\Facades\Url;
$url = Url::make('https://example.com/path?sort=desc');
$url = Url::make(' "https://example.com/path?sort=desc" ', 'header');
$url = Url::makeOrNull($request->header('origin'), 'header');
use Atldays\Url\UrlFactory;
$factory = app(UrlFactory::class);
$url = $factory->make('https://example.com');
$safeUrl = $factory->makeOrNull($rawValue, 'header');
The package provides Atldays\Url\Url, which extends Spatie's URL object and adds Laravel-oriented behavior.
use Atldays\Url\Url;
$url = Url::fromString('chrome-extension://extension-id/options.html');
$url->hasBrowserScheme(); // true
$url = Url::fromString('https://127.0.0.1:8080/ping');
$url->isIpHost(); // true
$url = Url::fromString('https://example.com:8443/path?x=1');
$url->getBase(); // https://example.com:8443
The recommended entry point for application code is UrlFactory or the Url facade.
Before the URL object is created, the factory runs the input through a configurable sanitizer pipeline.
When you do not pass a profile explicitly, the factory uses the configured default profile:
$url = Url::make($value);
$url = Url::make($value, 'header');
The package currently ships with two profiles:
default
General-purpose cleanup for regular application inputheader
Cleanup for header values such as Origin and RefererHeaderValueSanitizer
Trims wrapping quotes and header-specific whitespace noiseControlCharsSanitizer
Removes control characters before parsingUtf8Sanitizer
Normalizes broken UTF-8 before the final URL object is createduse Atldays\Url\Sanitizers\ControlCharsSanitizer;
use Atldays\Url\Sanitizers\HeaderValueSanitizer;
use Atldays\Url\Sanitizers\Utf8Sanitizer;
return [
'default_profile' => 'default',
'profiles' => [
'default' => [
ControlCharsSanitizer::class,
Utf8Sanitizer::class,
],
'header' => [
HeaderValueSanitizer::class,
ControlCharsSanitizer::class,
Utf8Sanitizer::class,
],
],
];
You can add your own sanitizer classes as long as they implement:
Atldays\Url\Sanitizers\UrlSanitizer
The package includes Laravel validation rules for both standard URLs and browser-specific URLs.
use Atldays\Url\Rules\Url;
Validator::make($data, [
'website' => ['nullable', new Url()],
]);
This rule:
nullableuse Atldays\Url\Rules\BrowserUrl;
Validator::make($data, [
'extension_url' => ['nullable', new BrowserUrl()],
]);
This rule only accepts browser-specific schemes such as:
chrome-extension://...moz-extension://...chrome://...edge://...opera://...The service provider registers a few request macros that return typed URL objects.
getUrlFromHeader$url = request()->getUrlFromHeader('origin');
getOriginUrl$origin = request()->getOriginUrl();
getRefererUrl$referer = request()->getRefererUrl();
getFullUrl$current = request()->getFullUrl();
These macros:
header profile when reading headersnull or the provided default when parsing failsspatie/laravel-data IntegrationIf your project uses spatie/laravel-data, the package provides casts and a transformer under src/Data.
UrlCastUse UrlCast when the incoming value must already be a valid URL.
use Atldays\Url\Data\Casts\UrlCast;
use Atldays\Url\Data\Transformers\UrlTransformer;
use Spatie\LaravelData\Attributes\WithCast;
use Spatie\LaravelData\Attributes\WithTransformer;
use Spatie\LaravelData\Data;
final class LinkData extends Data
{
public function __construct(
#[WithCast(UrlCast::class)]
#[WithTransformer(UrlTransformer::class)]
public \Atldays\Url\Contracts\Url|null $url,
) {}
}
ToUrlCastUse ToUrlCast when you want to coerce host-like values into full URLs.
Examples it can handle:
https://example.com/pathexample.com/pathexample.comuse Atldays\Url\Data\Casts\ToUrlCast;
final class HostData extends Data
{
public function __construct(
#[WithCast(ToUrlCast::class)]
public \Atldays\Url\Contracts\Url|null $url,
) {}
}
UrlTransformerUrlTransformer converts the URL object back to its string representation when the data object is transformed.
The package exposes a small set of contracts under Atldays\Url\Contracts, including:
UrlQuerySegmentUrlableThese contracts are useful when you want to type against abstractions instead of the concrete URL implementation.
Validation messages are provided through the package translation namespace:
url::validation.url
url::validation.browser_url
If you want to publish the package translations into your Laravel application and customize them, run:
php artisan vendor:publish --tag="url-translations"
After publishing, you can override the package translations in:
lang/vendor/url
Run the test suite:
composer test
Check formatting:
composer format:test
Auto-fix formatting:
composer format
The MIT License. Please see LICENSE.md for more information.
How can I help you explore Laravel packages today?