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.
Install via Composer
composer require jeremykendall/php-domain-parser
First Use Case: Parsing a Domain
use JeremyKendall\DomainParser\DomainParser;
$parser = new DomainParser();
$domain = $parser->parse('example.co.uk');
// Outputs:
// [
// 'domain' => 'example.co.uk',
// 'subdomains' => ['example'],
// 'mainDomain' => 'example.co.uk',
// 'tld' => 'co.uk',
// 'publicSuffix' => 'co.uk',
// 'effectiveTld' => 'uk',
// 'effectiveTldPlusOne' => 'co.uk',
// 'isValid' => true,
// ]
Where to Look First
DomainParser class for core functionality.DomainParser::parse() method for basic parsing.DomainParser::isValid() for validation checks.DomainName methods (withRootLabel, withoutRootLabel, isAbsolute, when) for advanced domain manipulation.Extracting Subdomains
$subdomains = $parser->parse('sub.example.co.uk')['subdomains'];
// ['sub', 'example']
Public Suffix List (PSL) Integration
$parser->updatePublicSuffixList();
Validation & Sanitization
if ($parser->isValid('invalid..domain')) {
// Process valid domain
}
Extracting TLDs
$tld = $parser->parse('blog.example.com')['effectiveTld']; // 'com'
$tldPlusOne = $parser->parse('blog.example.com')['effectiveTldPlusOne']; // 'example.com'
Batch Processing
$domains = ['example.com', 'test.co.uk', 'invalid'];
$results = array_map([$parser, 'parse'], $domains);
Absolute Domain Handling (New in 6.4.0)
use JeremyKendall\DomainParser\DomainName;
$domainName = DomainName::fromString('example.com');
if ($domainName->isAbsolute()) {
// Handle absolute domain (e.g., 'example.com.')
}
$withRootLabel = $domainName->withRootLabel(); // 'example.com.'
$withoutRootLabel = $domainName->withoutRootLabel(); // 'example.com'
Conditional Domain Building (New in 6.4.0)
$domain = DomainName::fromString('example.com')
->when($isSecure, fn($d) => $d->withScheme('https'))
->when($isSubdomain, fn($d) => $d->withSubdomain('app'));
Laravel Request Handling
Useful for extracting domains from Request objects:
use Illuminate\Http\Request;
$domain = $parser->parse(Request::server('HTTP_HOST'));
Middleware for Domain-Based Logic
public function handle(Request $request, Closure $next) {
$parsed = $parser->parse($request->getHost());
if ($parsed['effectiveTld'] === 'com') {
// Apply logic for .com domains
}
return $next($request);
}
Caching Parsed Results Store parsed domains in cache to avoid reprocessing:
$cacheKey = 'parsed:'.$domain;
$parsed = cache()->remember($cacheKey, now()->addHours(1), function() use ($parser, $domain) {
return $parser->parse($domain);
});
Absolute Domain Resolution (New in 6.4.0)
$domainName = DomainName::fromString('example.com.');
$resolved = $domainName->resolve(); // Resolves absolute domains without throwing exceptions
PSL Updates
updatePublicSuffixList() or configure auto-updates (if supported in future versions).Edge Cases in Parsing
example.xn--p1ai for example.рф) may require manual handling.192.168.1.1) will return isValid: false.example.com.) now resolve without exceptions (previously threw errors in older versions).Case Sensitivity
CO.UK vs co.uk). Normalize if needed:
$normalized = strtolower($parsed['domain']);
Performance with Large Batches
array_map with parallel processing (e.g., Laravel’s parallel() helper).Private Suffix Resolution (Fixed in 6.4.0)
*.example.local), ensure the cache is refreshed after upgrading:
$parser->updatePublicSuffixList(); // Refresh cache for private suffix fixes
Verify PSL Version
echo $parser->getPublicSuffixListVersion();
Check for Malformed Input
if (!$parser->isValid($domain)) {
log("Invalid domain: {$domain}");
}
Inspect Full Parsed Data
dd($parser->parse('complex.example.co.uk')); // Debug complex cases
Debug Absolute Domains (New in 6.4.0)
$domain = DomainName::fromString('example.com.');
dd($domain->isAbsolute(), $domain->resolve());
Custom PSL Rules
Override the default PSL by extending DomainParser:
class CustomDomainParser extends DomainParser {
protected function getPublicSuffixList(): string {
return file_get_contents('path/to/custom-psl.txt');
}
}
Adding Domain-Specific Logic Use parsed data to trigger custom logic:
$parsed = $parser->parse($domain);
if (in_array('shop', $parsed['subdomains'])) {
// Redirect to shopping cart
}
Testing Edge Cases Write tests for:
.ai, .tech).example.com.).*.example.local).Leveraging DomainName Methods (New in 6.4.0)
Extend functionality with:
$domain = DomainName::fromString('example.com')
->withSubdomain('app')
->withScheme('https')
->toString(); // 'app.example.com'
How can I help you explore Laravel packages today?