Installation:
composer require edsi-tech/gandi-bundle
Add to AppKernel.php (or bundles.php for Symfony 5+):
new EdsiTech\GandiBundle\EdsiTechGandiBundle(),
Configuration:
Add to config/packages/edsitech_gandi.yaml (Symfony 5+) or app/config/config.yml:
edsitech_gandi:
server_url: "https://rpc.gandi.net/xmlrpc/" # Use production URL
api_key: "%env(GANDI_API_KEY)%" # Store in .env
default_nameservers:
- ns1.yourdomain.com
- ns2.yourdomain.com
default_handles:
bill: YOURHANDLE-GANDI
tech: YOURHANDLE-GANDI
admin: YOURHANDLE-GANDI
owner: YOURHANDLE-GANDI
First Use Case: Fetch a domain’s expiration date:
$domainRepo = $container->get('edsitech_gandi.domain_repository');
$domain = $domainRepo->find('example.com');
echo $domain->getExpire()->format('Y-m-d');
Domain Management:
find() or findBy() for domain data (e.g., expiration, status).
$domains = $domainRepo->findBy(['handle' => 'MYHANDLE-GANDI']);
create() with required handles/nameservers:
$domainRepo->create('example.com', [
'nameservers' => ['ns1.yourdomain.com'],
'handles' => ['bill' => 'MYHANDLE-GANDI']
]);
DNS Records:
zone_repository to fetch/modify DNS zones:
$zoneRepo = $container->get('edsitech_gandi.zone_repository');
$zone = $zoneRepo->find('example.com');
$zone->addRecord('A', 'www', '192.0.2.1');
$zoneRepo->save($zone);
Bulk Operations:
findAll() for batch updates (e.g., renewals):
foreach ($domainRepo->findAll() as $domain) {
if ($domain->getExpire()->diff(new \DateTime())->days < 30) {
$domainRepo->renew($domain->getFqdn());
}
}
kernel.request) to auto-check domain expirations.CacheInterface) to reduce API calls:
$cache = $container->get('cache.app');
$domain = $cache->get('domain:example.com') ?: $domainRepo->find('example.com');
GandiApiException:
try {
$domainRepo->renew('example.com');
} catch (\EdsiTech\GandiBundle\Exception\GandiApiException $e) {
$this->addFlash('error', $e->getMessage());
}
API Key Security:
api_key in config.yml. Use .env and %env():
api_key: "%env(GANDI_API_KEY)%"
.env to gitignore.Rate Limits:
findAll() or bulk operations.Deprecated Methods:
getAvailableExtensions()) may return outdated data. Verify with Gandi’s official docs.XML-RPC Quirks:
Enable API Logging:
Add to config/packages/monolog.yaml:
handlers:
gandi:
type: stream
path: "%kernel.logs_dir%/gandi.log"
level: debug
channels: ["edsitech_gandi"]
Then configure the bundle to log requests:
edsitech_gandi:
debug: true
Test Server Pitfalls:
The test server (rpc.ote.gandi.net) may not reflect production data. Always test critical operations (e.g., renewals) in a staging environment.
Custom Handlers:
Override default handles by extending the DomainRepository:
class CustomDomainRepository extends \EdsiTech\GandiBundle\Repository\DomainRepository {
protected function getDefaultHandles() {
return ['bill' => 'CUSTOM-HANDLE-GANDI'];
}
}
Register as a service in config/services.yaml:
services:
edsitech_gandi.domain_repository:
class: App\Repository\CustomDomainRepository
Webhooks: Use Gandi’s webhooks for real-time events (e.g., domain expirations) and sync with the bundle’s local state.
Async Processing: Offload long-running operations (e.g., bulk DNS updates) to a queue (e.g., Symfony Messenger):
$message = new UpdateDnsZoneMessage('example.com', $records);
$bus->dispatch($message);
How can I help you explore Laravel packages today?