PHPackages                             pstoute/laravel-domain-registrar - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. pstoute/laravel-domain-registrar

ActiveLibrary[API Development](/categories/api)

pstoute/laravel-domain-registrar
================================

A unified domain registrar abstraction layer for Laravel, providing a single API to interact with multiple domain registrars

v1.0.0(3mo ago)0257MITPHPPHP ^8.2CI passing

Since Feb 3Pushed 3mo agoCompare

[ Source](https://github.com/pstoute/laravel-domain-registrar)[ Packagist](https://packagist.org/packages/pstoute/laravel-domain-registrar)[ RSS](/packages/pstoute-laravel-domain-registrar/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (7)Versions (2)Used By (0)

Laravel Domains
===============

[](#laravel-domains)

A unified domain registrar abstraction layer for Laravel, providing a single API to interact with multiple domain registrars.

Features
--------

[](#features)

- **Unified API**: Single interface for all registrar operations
- **Multiple Registrars**: Support for NameCheap, GoDaddy, Enom, OpenSRS, and Route53
- **Domain Management**: Register, renew, transfer, and manage domains
- **DNS Management**: Create, update, and delete DNS records
- **WHOIS**: Lookup and privacy management
- **Immutable DTOs**: Type-safe data transfer objects
- **Caching**: Built-in caching for API responses
- **Rate Limiting**: Respect registrar API limits
- **Testing**: Includes `FakeRegistrar` for application testing

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 10, 11, or 12

Installation
------------

[](#installation)

```
composer require pstoute/laravel-domain-registrar
```

Publish the configuration file:

```
php artisan vendor:publish --tag=domains-config
```

Configuration
-------------

[](#configuration)

Configure your registrars in `config/domains.php` or via environment variables:

```
DOMAIN_REGISTRAR=namecheap

# NameCheap
NAMECHEAP_API_USER=your_api_user
NAMECHEAP_API_KEY=your_api_key
NAMECHEAP_USERNAME=your_username
NAMECHEAP_CLIENT_IP=your_whitelisted_ip
NAMECHEAP_SANDBOX=false

# GoDaddy
GODADDY_API_KEY=your_api_key
GODADDY_API_SECRET=your_api_secret
GODADDY_SANDBOX=false

# Enom
ENOM_UID=your_uid
ENOM_PW=your_password
ENOM_SANDBOX=false

# OpenSRS
OPENSRS_USERNAME=your_username
OPENSRS_API_KEY=your_api_key
OPENSRS_SANDBOX=false

# Route53 (AWS)
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_DEFAULT_REGION=us-east-1
```

Basic Usage
-----------

[](#basic-usage)

### Using the Facade

[](#using-the-facade)

```
use Pstoute\LaravelDomains\Facades\Domains;

// Use the default registrar
$available = Domains::checkAvailability('example.com');

// Use a specific registrar
$domain = Domains::driver('godaddy')->getDomain('example.com');
```

### Using Dependency Injection

[](#using-dependency-injection)

```
use Pstoute\LaravelDomains\DomainsManager;

class DomainController extends Controller
{
    public function __construct(
        private DomainsManager $domains
    ) {}

    public function check(string $domain)
    {
        return $this->domains->checkAvailability($domain);
    }
}
```

Domain Operations
-----------------

[](#domain-operations)

### Check Availability

[](#check-availability)

```
use Pstoute\LaravelDomains\Facades\Domains;

// Single domain
$result = Domains::checkAvailability('example.com');

if ($result->available) {
    echo "Domain is available!";

    if ($result->premium) {
        echo "Premium price: {$result->price} {$result->currency}";
    }
}

// Multiple domains
$results = Domains::checkBulkAvailability([
    'example.com',
    'example.net',
    'example.org',
]);

foreach ($results as $result) {
    echo "{$result->domain}: " . ($result->available ? 'Available' : 'Taken');
}
```

### Register a Domain

[](#register-a-domain)

```
use Pstoute\LaravelDomains\Facades\Domains;
use Pstoute\LaravelDomains\Data\DomainContact;

$contact = new DomainContact(
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@example.com',
    phone: '+1.5551234567',
    address1: '123 Main St',
    city: 'New York',
    state: 'NY',
    postalCode: '10001',
    country: 'US',
    organization: 'ACME Corp', // optional
);

$domain = Domains::register('example.com', $contact, years: 2);

echo "Registered: {$domain->name}";
echo "Expires: {$domain->expiresAt->format('Y-m-d')}";
```

### Renew a Domain

[](#renew-a-domain)

```
$domain = Domains::renew('example.com', years: 1);

echo "New expiry: {$domain->expiresAt->format('Y-m-d')}";
```

### Transfer a Domain

[](#transfer-a-domain)

```
$domain = Domains::transfer(
    domain: 'example.com',
    authCode: 'AUTH-CODE-FROM-CURRENT-REGISTRAR',
    contact: $contact,
    years: 1
);
```

### Get Domain Information

[](#get-domain-information)

```
$domain = Domains::getDomain('example.com');

echo "Status: {$domain->status->value}";
echo "Expires: {$domain->expiresAt->format('Y-m-d')}";
echo "Auto-renew: " . ($domain->autoRenew ? 'Yes' : 'No');
echo "Locked: " . ($domain->locked ? 'Yes' : 'No');

// Check expiration
if ($domain->isExpiringSoon(days: 30)) {
    echo "Warning: Domain expires in {$domain->daysUntilExpiry()} days!";
}
```

### List All Domains

[](#list-all-domains)

```
$domains = Domains::listDomains(page: 1, perPage: 100);

foreach ($domains as $domain) {
    echo "{$domain->name} - {$domain->status->value}";
}
```

### Manage Nameservers

[](#manage-nameservers)

```
// Get current nameservers
$nameservers = Domains::getNameservers('example.com');

// Set new nameservers
Domains::setNameservers('example.com', [
    'ns1.cloudflare.com',
    'ns2.cloudflare.com',
]);
```

### Lock/Unlock Domain

[](#lockunlock-domain)

```
// Lock domain (prevent transfers)
Domains::lock('example.com');

// Unlock domain (allow transfers)
Domains::unlock('example.com');

// Get transfer auth code
$authCode = Domains::getAuthCode('example.com');
```

DNS Management
--------------

[](#dns-management)

### Get DNS Records

[](#get-dns-records)

```
$records = Domains::getDnsRecords('example.com');

foreach ($records as $record) {
    echo "{$record->type->value} {$record->name} -> {$record->value}";
}
```

### Create DNS Records

[](#create-dns-records)

```
use Pstoute\LaravelDomains\Data\DnsRecord;

// A record
$record = Domains::createDnsRecord(
    'example.com',
    DnsRecord::a('www', '192.168.1.1')
);

// AAAA record
Domains::createDnsRecord(
    'example.com',
    DnsRecord::aaaa('www', '2001:db8::1')
);

// CNAME record
Domains::createDnsRecord(
    'example.com',
    DnsRecord::cname('blog', 'example.github.io.')
);

// MX record with priority
Domains::createDnsRecord(
    'example.com',
    DnsRecord::mx('@', 'mail.example.com.', 10)
);

// TXT record (SPF, DKIM, etc.)
Domains::createDnsRecord(
    'example.com',
    DnsRecord::txt('@', 'v=spf1 include:_spf.google.com ~all')
);

// SRV record
Domains::createDnsRecord(
    'example.com',
    DnsRecord::srv('_sip._tcp', 'sipserver.example.com.', 10, 0, 5060)
);

// Custom TTL
Domains::createDnsRecord(
    'example.com',
    DnsRecord::a('api', '192.168.1.100', 300)
);
```

### Update DNS Record

[](#update-dns-record)

```
$record = new DnsRecord(
    type: 'A',
    name: 'www',
    content: '192.168.1.2',
    ttl: 3600,
    id: 'existing-record-id',
);

Domains::updateDnsRecord('example.com', 'existing-record-id', $record);
```

### Delete DNS Record

[](#delete-dns-record)

```
Domains::deleteDnsRecord('example.com', 'record-id');
```

WHOIS
-----

[](#whois)

### Lookup

[](#lookup)

```
$whois = Domains::whois('example.com');

echo "Available: " . ($whois->available ? 'Yes' : 'No');
echo "Registrar: {$whois->registrar}";
echo "Created: {$whois->createdAt?->format('Y-m-d')}";
echo "Expires: {$whois->expiresAt?->format('Y-m-d')}";
```

### WHOIS Privacy

[](#whois-privacy)

```
// Enable WHOIS privacy
Domains::enableWhoisPrivacy('example.com');

// Disable WHOIS privacy
Domains::disableWhoisPrivacy('example.com');
```

Pricing
-------

[](#pricing)

```
// Get pricing for a TLD
$pricing = Domains::getPricing('com');

echo "Registration: {$pricing->registrationPrice} {$pricing->currency}";
echo "Renewal: {$pricing->renewalPrice} {$pricing->currency}";
echo "Transfer: {$pricing->transferPrice} {$pricing->currency}";

// Sync all pricing
$allPricing = Domains::syncPricing();
```

Contact Management
------------------

[](#contact-management)

```
// Get domain contacts
$contacts = Domains::getContacts('example.com');

// Update contacts
Domains::updateContacts('example.com', [
    'registrant' => $newContact,
    'admin' => $adminContact,
    'tech' => $techContact,
]);
```

Testing
-------

[](#testing)

The package includes a `FakeRegistrar` for testing your application without making real API calls:

```
use Pstoute\LaravelDomains\Tests\Fakes\FakeRegistrar;
use Pstoute\LaravelDomains\DomainsManager;

class YourTest extends TestCase
{
    public function test_domain_registration()
    {
        $fake = new FakeRegistrar();
        $fake->setAvailable('newdomain.com');

        // Option 1: Bind to container
        $this->app->instance(DomainsManager::class, new class($fake) extends DomainsManager {
            public function __construct(private $fake) {}
            public function driver($driver = null) { return $this->fake; }
        });

        // Option 2: Use directly
        $result = $fake->checkAvailability('newdomain.com');
        $this->assertTrue($result->available);

        // Assert methods were called
        $fake->assertCalled('checkAvailability', ['newdomain.com']);
    }

    public function test_with_existing_domains()
    {
        $fake = new FakeRegistrar();
        $fake->addDomain('existing.com');
        $fake->addDomain('another.com', DomainStatus::Expired);

        $domains = $fake->listDomains();
        $this->assertCount(2, $domains);
    }

    public function test_failure_scenarios()
    {
        $fake = new FakeRegistrar();
        $fake->shouldFail('API Error');

        $this->expectException(RuntimeException::class);
        $fake->testConnection();
    }
}
```

Events
------

[](#events)

The package dispatches events for domain lifecycle operations:

- `DomainRegistered` - When a domain is registered
- `DomainRenewed` - When a domain is renewed
- `DomainTransferred` - When a domain transfer is initiated
- `DnsRecordCreated` - When a DNS record is created
- `DnsRecordUpdated` - When a DNS record is updated
- `DnsRecordDeleted` - When a DNS record is deleted

```
use Pstoute\LaravelDomains\Events\DomainRegistered;

class DomainRegisteredListener
{
    public function handle(DomainRegistered $event): void
    {
        Log::info("Domain registered: {$event->domain->name}");
        Log::info("Registrar: {$event->registrar}");
        Log::info("Years: {$event->years}");
    }
}
```

Supported Registrars
--------------------

[](#supported-registrars)

RegistrarRegistrationDNSWHOISNotesNameCheap✅✅✅Full supportGoDaddy✅✅✅Full supportEnom✅✅✅30 req/min rate limitOpenSRS✅✅✅MD5 signature authRoute53❌✅❌DNS-only (requires aws/aws-sdk-php)Error Handling
--------------

[](#error-handling)

The package throws specific exceptions for different error conditions:

```
use Pstoute\LaravelDomains\Exceptions\{
    RegistrarException,
    AuthenticationException,
    RateLimitException,
    DomainNotFoundException,
    DomainUnavailableException,
    ConfigurationException,
    OperationNotSupportedException,
};

try {
    $domain = Domains::register('example.com', $contact);
} catch (DomainUnavailableException $e) {
    // Domain is already registered
} catch (AuthenticationException $e) {
    // Invalid API credentials
} catch (RateLimitException $e) {
    // Too many requests, retry after $e->retryAfter seconds
} catch (RegistrarException $e) {
    // General registrar error
    Log::error("Registrar error: {$e->getMessage()}", [
        'registrar' => $e->registrar,
        'context' => $e->context,
    ]);
}
```

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance80

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

104d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f809227e1e4c6e364e83cda5f2ebe4b144dd738685da480baa2fc2e120a57125?d=identicon)[pstoute](/maintainers/pstoute)

---

Top Contributors

[![pstoute](https://avatars.githubusercontent.com/u/669308?v=4)](https://github.com/pstoute "pstoute (3 commits)")

---

Tags

laraveldnsdomainsregistrarroute53namecheapgodaddyenomopensrs

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/pstoute-laravel-domain-registrar/health.svg)

```
[![Health](https://phpackages.com/badges/pstoute-laravel-domain-registrar/health.svg)](https://phpackages.com/packages/pstoute-laravel-domain-registrar)
```

###  Alternatives

[laravel/socialite

Laravel wrapper around OAuth 1 &amp; OAuth 2 libraries.

5.7k96.9M674](/packages/laravel-socialite)[laravel/cashier-paddle

Cashier Paddle provides an expressive, fluent interface to Paddle's subscription billing services.

264778.4k3](/packages/laravel-cashier-paddle)[simplestats-io/laravel-client

Client for SimpleStats!

4515.5k](/packages/simplestats-io-laravel-client)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[dragon-code/laravel-json-response

Automatically always return a response in JSON format

1118.6k1](/packages/dragon-code-laravel-json-response)[truckersmp/steam-socialite

Laravel Socialite provider for Steam OpenID.

1516.7k](/packages/truckersmp-steam-socialite)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
