spatie/dns
Fetch DNS records in PHP using dig. Query domains for A, AAAA, CNAME, MX, TXT, SRV and more, filter by type(s), and get structured record objects with handy accessors for record details.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require spatie/dns
No additional configuration is required for basic usage.
First Use Case:
Fetch all DNS records for a domain (e.g., google.com):
use Spatie\Dns\Dns;
$records = Dns::getRecords('google.com');
dd($records); // Returns a collection of DNSRecord objects
Key Classes:
Dns: Main facade for querying DNS records.DNSRecord: Represents individual records (e.g., A, MX, TXT).CouldNotFetchDns: Updated exception class (previously DnsException) now includes dig exit code for debugging.DnsException: Legacy alias (deprecated in favor of CouldNotFetchDns).Where to Look First:
src/DnsServiceProvider.php (service provider setup).src/Dns.php (core facade logic).src/Exceptions/CouldNotFetchDns.php (updated exception with exit code).Filter records by type (e.g., MX, TXT, A):
$mxRecords = Dns::getRecords('example.com')->whereType('MX');
$txtRecords = Dns::getRecords('example.com')->whereType('TXT');
Avoid repeated DNS lookups by caching results (e.g., for rate-limited APIs or slow DNS providers):
$records = Cache::remember("dns_records_{$domain}", now()->addHours(1), function () use ($domain) {
return Dns::getRecords($domain);
});
Use try-catch blocks for DNS resolution errors. Now leverages the updated CouldNotFetchDns exception:
try {
$records = Dns::getRecords('nonexistent.example');
} catch (CouldNotFetchDns $e) {
Log::error("DNS lookup failed for nonexistent.example. Exit code: {$e->getExitCode()}. Message: " . $e->getMessage());
// Fallback logic (e.g., return cached data or default values)
}
Offload DNS lookups to background jobs (e.g., for bulk domain checks):
use Spatie\Dns\Jobs\GetRecords;
GetRecords::dispatch('example.com')
->afterCommit()
->onQueue('dns');
Extend the package to support custom DNS resolvers (e.g., internal DNS servers):
use Spatie\Dns\DnsProvider;
class CustomDnsProvider implements DnsProvider {
public function getRecords(string $domain): array {
// Implement custom logic (e.g., call internal API)
return ['type' => 'A', 'data' => '192.0.2.1'];
}
}
// Register in AppServiceProvider:
Dns::extend('custom', function () {
return new CustomDnsProvider();
});
// Usage:
Dns::onProvider('custom')->getRecords('example.com');
Process multiple domains efficiently:
$domains = ['google.com', 'github.com', 'spatie.be'];
$results = collect($domains)->map(fn ($domain) => Dns::getRecords($domain));
Validate domain ownership via DNS (e.g., check for TXT records):
$txtRecords = Dns::getRecords($domain)->whereType('TXT');
$hasVerification = $txtRecords->contains(fn ($record) =>
str_contains($record->data, 'verification-code=12345')
);
MX records).TXT entries).Spatie\Dns\Dns in unit tests:
$this->mock(Spatie\Dns\Dns::class, function ($mock) {
$mock->shouldReceive('getRecords')
->with('example.com')
->andReturn(collect([new DNSRecord(['type' => 'A', 'data' => '1.1.1.1'])]));
});
chunk() or cursor() for large datasets.Spatie\Async for concurrent DNS lookups:
use Spatie\Async\Parallel;
Parallel::make($domains)->each(function ($domain) {
return Dns::getRecords($domain);
});
Rate Limiting:
8.8.8.8) throttle requests.use Symfony\Component\Process\Exception\ProcessTimedOutException;
try {
$records = Dns::getRecords($domain);
} catch (ProcessTimedOutException $e) {
sleep(2); // Wait before retry
retry();
}
TTL (Time-to-Live) Caching:
Dns::flushCache() (if supported) or implement local caching with short TTLs.DNSSEC Validation:
rubensworks/dnssec-validator for additional checks.Non-Standard Record Types:
CAA, SRV) may not be parsed correctly.DNSRecord or pre-process raw data:
$rawRecords = Dns::getRecords($domain, true); // Get raw output
Local Development:
/etc/hosts or C:\Windows\System32\drivers\etc\hosts overrides are present.google.com) or mock DNS responses.Case Sensitivity:
$domain = strtolower($domain);
Exception Handling:
DnsException is now an alias for CouldNotFetchDns, which includes the dig exit code for better debugging.CouldNotFetchDns for detailed error information:
catch (CouldNotFetchDns $e) {
Log::error("Exit code: {$e->getExitCode()}, Message: " . $e->getMessage());
}
Enable Verbose Output:
Dns::enableVerboseOutput(); // Logs raw DNS queries/responses
Check Underlying Process:
The package uses exec() to call dig or nslookup. Verify these tools are installed:
dig google.com
nslookup google.com
Inspect Raw Data: Access raw DNS output for debugging:
$rawOutput = Dns::getRecords($domain, true);
dd($rawOutput);
Common Errors:
dig/nslookup is installed.
Fix: Install via brew install bind (macOS) or apt-get install dnsutils (Linux).max_execution_time or use a faster DNS provider.CouldNotFetchDns exception to diagnose dig failures:
catch (CouldNotFetchDns $e) {
if ($e->getExitCode() === 1) {
//
How can I help you explore Laravel packages today?