Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Whois Laravel Package

setechsolutions/php-whois

A PHP package for performing WHOIS lookups on domains, retrieving registration and ownership details from WHOIS servers. Useful for domain availability checks, expiry information, and DNS-related tooling in Laravel or plain PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with composer require setechsolutions/php-whois. There is no service provider to register — Laravel's package discovery picks up the provider and the Whois facade, so the fastest first check is a tinker session:

Whois::lookup('example.com');   // DomainInfo, or null when the domain is not registered

Three places to look first, in this order:

  1. DomainInfo — the only result type. Everything is a method call, not a property: domain(), registrar(), owner(), createdAt(), expiresAt(), updatedAt(), statuses(), nameServers(). Dates are DateTimeImmutable or null; the object is immutable and JSON-serializable, which makes it safe to pass around and cache.
  2. config/whois.php — publish it (php artisan vendor:publish) only when you need to change defaults. WHOIS_MODE and WHOIS_TIMEOUT are the two knobs you will realistically touch, and both are read through config, so config:cache applies.
  3. The exception hierarchy — everything extends WhoisException, with InvalidDomainException, UnsupportedTldException, ConnectionException and RateLimitException underneath. Catching the base class is enough to start; catching the subclasses is what makes the UX good later.

First real use case: an availability check on the domain-search field of a signup or checkout flow. Validate the string is a domain (the package throws InvalidDomainException before any request, which is a useful free validation layer), call isAvailable(), and render "taken" only when you get a definitive answer — see the gotchas below.

Implementation Patterns

Availability check with a three-way outcome. null from lookup() means "not registered"; exceptions mean "we could not answer". Collapse those two into "available" and you will hand out domains you don't own.

use SETechSolutions\Whois\Whois;
use SETechSolutions\Whois\Exceptions\WhoisException;
use SETechSolutions\Whois\Exceptions\InvalidDomainException;
use SETechSolutions\Whois\Exceptions\UnsupportedTldException;

try {
    $info = Whois::lookup($domain);
} catch (InvalidDomainException $e) {
    return back()->withErrors(['domain' => 'Not a valid domain name.']);
} catch (UnsupportedTldException $e) {
    return back()->withErrors(['domain' => 'We cannot check that TLD automatically.']);
} catch (WhoisException $e) {
    report($e);
    return back()->withErrors(['domain' => 'Lookup failed, try again shortly.']);
}

$available = $info === null;

Renewal / expiry dashboard. The package is at its best as a scheduled enrichment job rather than a request-time call. Store domain, registrar, expires_at and refresh nightly; expiresAt() being null is normal for registries that don't publish dates in a machine-readable way, so treat it as "unknown", not "expired".

$info->expiresAt()?->format('Y-m-d') ?? 'unknown';

Cache aggressively, but cache the object. MemcachedLoader is gone in 5.0, so caching is your job. DomainInfo is immutable and JSON-serializable, so Cache::remember("whois:{$domain}", now()->addHours(12), fn () => Whois::lookup($domain)) works, and toArray() gives you a flat payload when you only need fields for a table or an API response. Registration data changes on the order of days, so a 6–24 hour TTL removes almost all of your lookup volume.

Bulk work goes on the queue, with per-domain failure isolation.

foreach ($domains->chunk(50) as $chunk) {
    foreach ($chunk as $domain) {
        CheckDomainJob::dispatch($domain);
    }
}

Catch RateLimitException inside the job and release() with backoff rather than letting the whole batch fail — RDAP endpoints in particular have published rate limits, and the package raises the same exception for both protocols.

Mode and servers as configuration, not code. Set WHOIS_MODE per environment (rdap_first is the sensible default; whois_only locally if you're behind a proxy that blocks RDAP). rdap_servers and whois_servers passed in the options array are tried before the bundled servers for that zone, which is the clean way to point at a private or regional registry, or at a stub during manual testing.

new Whois(['mode' => Mode::WHOIS_ONLY, 'timeout' => 10]);

raw() is your debugging tool, not your production path. When a parser returns something surprising for a specific TLD, drop into raw($domain)->text() in a one-off artisan command or tinker to see what the registry actually sent. Calling it in a live request doubles your network calls.

Gotchas and Tips

  • null is not an error, and an exception is not availability. The single most common bug with this package is $available = Whois::lookup($d) === null without a try/catch, which turns a timeout into a "domain is free" message.
  • Null dates are the norm, not the exception. The 4.x habit of $info->expirationDate returning 0 is gone; every date accessor can return null. Any ->format() without ?-> is a latent fatal error. The README example is the happy path only.
  • The 30-second default timeout is too long for a web request. A hung WHOIS server will hold a PHP-FPM worker for half a minute. Set timeout to 5–10 in the config for synchronous use, or push lookups to the queue. curl_options is available if you want a separate connect timeout.
  • Input validation is strict but literal. InvalidDomainException fires for anything that isn't a bare domain name — https://example.com, example.com/path, an email address. Normalise and strip before calling. Unidata/IDN domains should go through idn_to_ascii() first, since punycode conversion is not something to assume.
  • 5.0 is a hard break, and there is no replace entry any more. The Iodev\Whois namespace, Factory, the loaders and ASN lookups are all gone. If another dependency still requires io-developer/php-whois, Composer will now install both packages side by side rather than treating this one as a substitute — expect duplicated WHOIS logic and confusing class names. Projects relying on the drop-in replacement should stay on ^4.2 (the 4.x branch), and the migration table in the release notes is worth working through line by line rather than searching for Iodev\ imports.
  • follow_registrar costs a second round trip. Enabling it gets you richer registrant data at the price of latency and another chance to be rate-limited. Enable it in the queued enrichment job, not in the checkout path.
  • ASN and Memcached are your problem now. ASN lookups need a different package or a whois -h shell-out; caching needs Cache::remember around toArray() or the object itself.
  • Config caching bites in the usual way. WHOIS_MODE and WHOIS_TIMEOUT are read from config/whois.php, so changing .env on a server with a cached config does nothing until php artisan config:cache is re-run. If the facade isn't found, check that package discovery hasn't been disabled in composer.json.
  • Don't hit the network in tests. Because the facade is auto-discovered you can swap it (Whois::shouldReceive('lookup')->andReturn(...)), but the cleanest long-term move is a thin DomainLookup interface of your own that returns DomainInfo/null, bound to the real Whois in production and a fake in tests. That also gives you one place to attach the cache.
  • PHP floor is 7.2.5, and CI covers 7.2 through 8.5 plus Laravel 6 through 13. If you write 8.x-only syntax in the surrounding code, keep it out of anything shared with the package's supported range, and check your matrix matches before upgrading an old app.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons