jeremykendall/php-domain-parser
Parse, validate, and normalize domains, subdomains, and suffixes using the Public Suffix List. Extract registrable domain vs. subdomain, handle IDNs and edge cases, and keep parsing rules current via PSL updates—ideal for URL processing, cookies, and security checks.
withRootLabel, withoutRootLabel, isAbsolute) improve support for absolute domain names (e.g., example.com. vs. example.com), critical for:
example.com vs. example.com. in routing).DomainName::when() enables dynamic domain construction (e.g., conditional subdomains), useful for:
staging.example.com vs. prod.example.com).test-variant.example.com).*.internal.company) aligns with:
*.aws.internal).Host headers in HTTP/3).example.com. vs. example.com).isAbsolute() to normalize inputs in middleware/request validation.when):
DomainBuilder).*.private).php-domain-parser:clear-cache).composer require jeremykendall/php-domain-parser:^6.4.0
php artisan vendor:publish --provider="JeremyKendall\DomainParser\DomainParserServiceProvider" --tag="config"
php artisan domain-parser:clear-cache
example.com.) may cause unexpected behavior in downstream systems.$domain = $parser->parse($input)->withoutRootLabel();
when() could lead to hard-to-debug domain chains.example.com. from APIs)?*.internal)? If so, test the fix with your existing rules.when() be used for runtime logic (e.g., feature flags) or static configs?when() method add overhead for high-frequency parsing (e.g., 10K+ RPS)?Request facade to normalize Host headers:
$domain = app(DomainService::class)->parse(request()->host)->withoutRootLabel();
Route::domain('{sub}.example.com')->when(fn() => config('features.subdomains'))).it('parses absolute domains', function () {
$parser = new DomainParser();
expect($parser->parse('example.com.')->isAbsolute())->toBeTrue();
});
publicsuffixlist/publicsuffixlist-php (though less maintained).php-domain-parser:clear-cache works in staging.composer.json and run:
composer update jeremykendall/php-domain-parser
php artisan domain-parser:clear-cache
DomainService to use new methods:
class DomainService {
public function normalize(string $domain): string {
return $this->parser->parse($domain)->withoutRootLabel()->toString();
}
public function isAbsoluteDomain(string $domain): bool {
return $this->parser->parse($domain)->isAbsolute();
}
}
// app/Http/Middleware/ParseDomain.php
public function handle($request, Closure $next) {
$domain = app(DomainService::class)->normalize($request->host);
$request->merge(['normalized_domain' => $domain]);
return $next($request);
}
6.3.x.# .github/workflows/deploy.yml
- run: php artisan domain-parser:clear-cache
withoutRootLabel() to all domain inputs (e.g., Host headers, user uploads).when() for dynamic use cases (e.g., feature flags).example.com. in production).php artisan domain-parser:clear-cache post-deploy or post-PSL-update.PrivateSuffixException).isAbsolute() to audit domain inputs:
$domain = $parser->parse($input);
if ($domain->isAbsolute()) {
logger()->warning("Absolute domain detected: {$domain}");
}
parsed_domain events).## Domain Parsing Runbook
1. **Cache Issues**: Run `php artisan domain-parser:clear-cache`.
2.
How can I help you explore Laravel packages today?