Drivers
Cloudflare DNS Driver
Introduction
The Cloudflare DNS Driver provides a fully typed interface for managing DNS zones and records via the Cloudflare API v4. It uses the Kipchak HTTP driver as its HTTP client, so no additional HTTP library is required.
Key features include:
- Multiple Connections: Configure separate API tokens for multiple Cloudflare accounts.
- Fully Typed API: Dedicated request objects, result objects, and enums — your IDE will guide you through every call.
- Zone Management: List and inspect zones.
- DNS Record Management: Create, read, full-replace (PUT), partial-update (PATCH), and delete records.
- All Record Types: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, and all other types supported by Cloudflare.
Installation
Install the driver via Composer:
composer require kipchak/driver-cloudflare-dns
Initialise the Driver
Add the following to your drivers/drivers.php file. The Cloudflare DNS driver depends on the Config and HTTP drivers, so it must be initialised after them:
use Kipchak\Driver\CloudflareDns\CloudflareDns;
CloudflareDns::initialise($container);
Configuration
Create a file named kipchak.cloudflare-dns.php in your project's config/ directory.
Connection Settings
Define one or more named connections under the connections key:
api_token(required): A Cloudflare API Token with Zone:Read and DNS:Edit permissions.base_url(optional): Override the API base URL. Defaults tohttps://api.cloudflare.com/client/v4.
Example Configuration
<?php
use function Kipchak\Core\env;
return [
'connections' => [
'default' => [
'api_token' => env('CF_API_TOKEN', ''),
],
// Add further named connections for multiple Cloudflare accounts:
// 'secondary' => [
// 'api_token' => env('CF_SECONDARY_API_TOKEN', ''),
// ],
],
];
Environment Variables
CF_API_TOKEN=your-cloudflare-api-token
Usage
Retrieve a connection by name. If no name is given, default is used.
use Kipchak\Driver\CloudflareDns\CloudflareDns;
$cf = CloudflareDns::get(); // 'default' connection
$cf = CloudflareDns::get('secondary'); // named connection
Zones
use Kipchak\Driver\CloudflareDns\Enum\ZoneStatus;
use Kipchak\Driver\CloudflareDns\Request\ListZonesRequest;
// List all zones — returns ZoneResult[]
$zones = $cf->listZones();
// Filter by name and status
$zones = $cf->listZones(new ListZonesRequest(
name: 'example.com',
status: ZoneStatus::Active,
));
foreach ($zones as $zone) {
echo $zone->id;
echo $zone->name;
echo $zone->status->value; // 'active'
}
// Get a single zone — returns ZoneResult
$zone = $cf->getZone('023e105f4ecef8ad9ca31a8372d0c353');
Listing DNS Records
use Kipchak\Driver\CloudflareDns\Enum\DnsRecordType;
use Kipchak\Driver\CloudflareDns\Request\ListDnsRecordsRequest;
$zoneId = '023e105f4ecef8ad9ca31a8372d0c353';
// List all records — returns DnsRecordResult[]
$records = $cf->listDnsRecords($zoneId);
// Filter by type and name
$records = $cf->listDnsRecords($zoneId, new ListDnsRecordsRequest(
type: DnsRecordType::A,
name: 'api.example.com',
));
// Get a single record — returns DnsRecordResult
$record = $cf->getDnsRecord($zoneId, 'dns-record-id');
echo $record->type->value; // 'A'
echo $record->content; // '192.0.2.1'
Creating a DNS Record
use Kipchak\Driver\CloudflareDns\Request\CreateDnsRecordRequest;
// A record
$record = $cf->createDnsRecord($zoneId, new CreateDnsRecordRequest(
type: DnsRecordType::A,
name: 'api.example.com',
content: '192.0.2.1',
ttl: 1, // 1 = automatic
proxied: false,
comment: 'API server',
));
// MX record (priority required)
$record = $cf->createDnsRecord($zoneId, new CreateDnsRecordRequest(
type: DnsRecordType::MX,
name: 'example.com',
content: 'mail.example.com',
priority: 10,
));
Updating a DNS Record
Use updateDnsRecord (PUT) for a full replacement where all fields must be supplied, or patchDnsRecord (PATCH) to change only specific fields.
use Kipchak\Driver\CloudflareDns\Request\PatchDnsRecordRequest;
use Kipchak\Driver\CloudflareDns\Request\UpdateDnsRecordRequest;
$recordId = 'dns-record-id';
// Full replacement — all fields sent to Cloudflare
$record = $cf->updateDnsRecord($zoneId, $recordId, new UpdateDnsRecordRequest(
type: DnsRecordType::A,
name: 'api.example.com',
content: '192.0.2.2',
proxied: false,
));
// Partial update — only the supplied fields are changed
$record = $cf->patchDnsRecord($zoneId, $recordId, new PatchDnsRecordRequest(
content: '192.0.2.3',
));
Deleting a DNS Record
// Throws RuntimeException on failure; returns void on success
$cf->deleteDnsRecord($zoneId, 'dns-record-id');
Type Reference
Enums
| Enum | Values |
|---|---|
DnsRecordType | A AAAA CAA CERT CNAME DNSKEY DS HTTPS LOC MX NAPTR NS PTR SMIMEA SOA SRV SSHFP SVCB TLSA TXT URI |
ZoneStatus | Active Pending Initializing Moved |
Request Objects
| Class | Used for | Required fields |
|---|---|---|
ListZonesRequest | Filtering listZones() | none |
ListDnsRecordsRequest | Filtering listDnsRecords() | none |
CreateDnsRecordRequest | createDnsRecord() | type, name, content |
UpdateDnsRecordRequest | updateDnsRecord() (full replace) | type, name, content |
PatchDnsRecordRequest | patchDnsRecord() (partial update) | none |
Result Objects
| Class | Returned by |
|---|---|
ZoneResult | listZones(), getZone() |
DnsRecordResult | listDnsRecords(), getDnsRecord(), createDnsRecord(), updateDnsRecord(), patchDnsRecord() |
Error Handling
All methods throw a RuntimeException when the Cloudflare API returns an error. The message includes the Cloudflare error code and the HTTP status:
[CF 7003] Could not route to /zones. (HTTP 400)
Git Repository
The source code for this driver is available on 1x.ax at https://1x.ax/mamluk/kipchak/drivers/cloudflare-dns.