srustamov/gcore-php

PHP client for the Gcore API (CDN, DNS, FastEdge)

Maintainers

Package info

github.com/srustamov/gcore-php

pkg:composer/srustamov/gcore-php

Transparency log

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-25 11:53 UTC

This package is auto-updated.

Last update: 2026-07-27 10:55:24 UTC


README

PHP client for the Gcore API.

Gcore publishes an official Python SDK but no PHP one. This package covers CDN, DNS and FastEdge. The API surface is generated from Gcore's published OpenAPI specifications; the transport, retry, and hydration layers are hand-written.

Requirements

  • PHP 8.2 or newer
  • ext-json

Installation

composer require srustamov/gcore-php

Getting started

use Gcore\Client;

$gcore = new Client(apiKey: getenv('GCORE_API_KEY'));

$zone = $gcore->dns->zones->get('example.com');
echo $zone->name;

The API key falls back to the GCORE_API_KEY environment variable when the argument is omitted.

Pagination

List endpoints return a lazy Paginator. Iterating it walks every page, so you never deal with offsets yourself.

foreach ($gcore->dns->zones->list() as $zone) {
    echo $zone->name, PHP_EOL;
}

Pagination is driven through the returned object, not through the call that creates it:

$paginator = $gcore->dns->zones->list();

$firstPage = $paginator->page(limit: 20);        // one page
$everything = $paginator->all();                 // materialize all pages
$total = $paginator->count();                    // server-reported total

Filters, on the other hand, are arguments. Array filters repeat the query key, which is what the API expects:

$gcore->dns->zones->list(orderBy: 'name', id: [1, 2]);
// GET /dns/v2/zones?order_by=name&id=1&id=2

Working with records

$gcore->dns->rrsets->create('example.com', 'www.example.com', 'A', [
    'ttl' => 300,
    'resource_records' => [
        ['content' => ['1.2.3.4']],
    ],
]);

foreach ($gcore->dns->rrsets->list('example.com') as $rrset) {
    echo $rrset->name, ' ', $rrset->ttl, PHP_EOL;
}

Request bodies are associative arrays. Their shapes are documented as array{...} PHPDoc on each method, so PhpStorm and PHPStan can check them without the library shipping a parameter class per endpoint.

Undocumented fields

Models expose typed properties for everything the specification documents, and raw() for everything else. A field Gcore adds after this release is still reachable without waiting for a new version.

$zone = $gcore->dns->zones->get('example.com');

$zone->name;                      // typed
$zone->raw()['brand_new_field'];  // whatever the API actually returned

toArray() and jsonSerialize() return the same raw payload, so a model round-trips exactly what the server sent.

Error handling

Every failure is a Gcore\Exception\GcoreException. Non-2xx responses raise a subclass of ApiException chosen by status code.

use Gcore\Exception\NotFoundException;
use Gcore\Exception\RateLimitException;

try {
    $gcore->dns->zones->get('missing.example');
} catch (NotFoundException $e) {
    echo $e->statusCode;   // 404
    echo $e->rawBody;      // the response body, verbatim
} catch (RateLimitException $e) {
    // already retried per the retry policy before reaching you
}
Status Exception
400 BadRequestException
401 AuthenticationException
403 PermissionDeniedException
404 NotFoundException
409 ConflictException
422 UnprocessableEntityException
429 RateLimitException
5xx ServerException
network, timeout ConnectionException

The three Gcore products in scope document no shared error body, so the message is taken from whichever of message, error, detail, or errors is present, falling back to the HTTP reason phrase. rawBody is always kept.

Configuration

$gcore = new Client(
    apiKey: '...',
    baseUrl: 'https://api.gcore.com',
    timeout: 30.0,
    maxRetries: 2,
    headers: ['X-Trace' => 'abc'],
);

Requests retry on 408, 409, 429, and 5xx responses, and on connection errors, with exponential backoff plus jitter capped at 8 seconds. A numeric Retry-After header wins over the computed delay. Any single call can override the defaults:

use Gcore\RequestOptions;

$gcore->dns->zones->get('example.com', new RequestOptions(timeout: 5.0, maxRetries: 0));

Coverage

Product Resources Models Accessor
CDN 18 220 $gcore->cdn
DNS 10 50 $gcore->dns
FastEdge 7 30 $gcore->fastedge
Cloud Not planned for v1

Development

This section is for working in the repository. The generator is not part of the installed package — composer require ships src/ and nothing else.

src/Cdn, src/Dns and src/Fastedge are generated. Do not edit them by hand — change the emitters under codegen/ and regenerate:

php codegen/bin/generate.php dns       # or cdn, or fastedge
vendor/bin/php-cs-fixer fix
vendor/bin/phpunit

Formatting is a required step, not a tidy-up: the emitters produce output that php-cs-fixer then normalizes, so the zero-diff check below only holds once it has run.

Where the naming rules cannot produce a good name — CDN puts three separate collections under one Logs uploader tag, for instance — codegen/overrides.php maps the path to the name it should have.

Regenerating an unchanged specification produces no diff, and CI enforces that, so a hand-edit under a generated directory fails the build rather than being silently erased by the next run.

php codegen/bin/check-drift.php reports when a vendored specification has fallen behind the published one.

License

MIT