Search by

siteapps / openholiday

siteapps

Typed PHP SDK for every OpenHolidays API v1 endpoint.

Package info

github.com/Siteappsnl/OpenHolidayAPI

pkg:composer/siteapps/openholiday

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-10-14 09:46 UTC

This package is auto-updated.

Last update: 2026-10-14 09:47:55 UTC


README

Een zelfstandig Composer-package voor alle 10 GET-endpoints uit de OpenHolidays API v1-specificatie.

  • Namespace: Siteapps\OpenHoliday
  • Composer-package: siteapps/openholiday
  • PHP 8.4 of hoger binnen PHP 8.x (^8.4), met ext-curl en ext-json
  • PSR-4-autoloading, strict_types, readonly modellen en PHP-enums
  • Alle 15 schema's: 12 modellen en 3 API-enums
  • JSON naar getypeerde modellen; CSV en ICS als onbewerkte response
  • Alle filters, recursieve regio's/groepen, vertalingen en statistieken
  • Onderscheid tussen netwerkfouten, HTTP-fouten en ongeldige responses
  • Geen externe PHP-package-afhankelijkheden, API-key of framework nodig

Installatie

Pak de ZIP uit. In de map openholiday:

composer install
composer check
php examples/basic.php

Toevoegen aan een bestaand project

Zet openholiday bijvoorbeeld naast je applicatiemap. Voer in je applicatie uit:

composer require 'siteapps/openholiday'

Pas het pad aan als je de SDK in een andere map zet. Een Composer path-repository verwijst naar de uitgepakte broncode; die map moet dus beschikbaar blijven.

Het package is niet gepubliceerd op Packagist. Voor gedeeld gebruik kun je deze map in een eigen Git-repository plaatsen, een versie taggen en die repository als Composer VCS-repository toevoegen. Er is bewust geen composer.lock opgenomen: dit is een herbruikbare library; de applicatie beheert haar eigen lockfile.

Snel beginnen

<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use Siteapps\OpenHoliday\Client;

$client = new Client();

$holidays = $client->getPublicHolidays(
    countryIsoCode: 'NL',
    validFrom: '2026-01-01',
    validTo: '2026-12-31',
    languageIsoCode: 'NL',
);

foreach ($holidays as $holiday) {
    echo $holiday->startDate->format('d-m-Y')
        . ' — ' . $holiday->getName('NL') . PHP_EOL;
}

Alle endpoints

$client->getCountries(languageIsoCode: 'NL');
$client->getLanguages(languageIsoCode: 'NL');
$client->getSubdivisions(countryIsoCode: 'NL', languageIsoCode: 'NL');
$client->getGroups(countryIsoCode: 'NL', languageIsoCode: 'NL');

$client->getPublicHolidays('NL', '2026-01-01', '2026-12-31', 'NL');
$client->getSchoolHolidays('NL', '2026-01-01', '2026-12-31', 'NL');

// Deze twee endpoints leveren resultaten uit alle landen, met een country-reference.
$client->getPublicHolidaysByDate('2026-12-25', 'NL');
$client->getSchoolHolidaysByDate('2026-12-25', 'NL');

$client->getPublicHolidayStatistics(countryIsoCode: 'NL');
$client->getSchoolHolidayStatistics(countryIsoCode: 'NL');

Zie docs/endpoints.md voor de koppeling aan de API-paden, returntypes en exportformaten. Een leeg resultaat is steeds [].

Regio- en groepsfilters

Gebruik de code uit getSubdivisions() en getGroups(). Een subdivision-code is niet noodzakelijk gelijk aan de optionele isoCode van een subdivision. Groepen en regio's kunnen genest zijn in children; de SDK hydrateert deze recursief.

$subdivisions = $client->getSubdivisions('NL', 'NL');

foreach ($subdivisions as $subdivision) {
    $holidays = $client->getSchoolHolidays(
        countryIsoCode: 'NL',
        validFrom: '2026-01-01',
        validTo: '2026-12-31',
        languageIsoCode: 'NL',
        subdivisionCode: $subdivision->code,
    );
}

// groupCode is beschikbaar op getSchoolHolidays() en getSchoolHolidayStatistics().
// subdivisionCode is daarnaast beschikbaar op getGroups(), getPublicHolidays()
// en getPublicHolidayStatistics(). Vul de exacte code uit de API in.

Datums en vertalingen

Datumparameters accepteren YYYY-MM-DD of DateTimeInterface. Een ingegeven DateTime behoudt zijn lokale kalenderdatum; er vindt geen tijdzoneverschuiving plaats. Ongeldige kalenderdatums en een omgekeerde datumreeks worden vóór de HTTP-aanroep geweigerd met InvalidArgumentException.

Responsevelden met formaat date worden DateTimeImmutable op middernacht UTC. Bij toArray() en JSON-serialisatie worden ze opnieuw YYYY-MM-DD.

getName('NL') zoekt hoofdletterongevoelig naar de Nederlandse naam, daarna naar Engels en vervolgens naar de eerste beschikbare naam. Met getName('NL', 'DE') verander je de fallbacktaal; getName('NL', null) slaat de expliciete fallbacktaal over. Zonder namen is het resultaat null.

Modellen en enums

Modellen staan in Siteapps\OpenHoliday\Model en dragen de namen uit OpenAPI, zoals HolidayResponse, CountryResponse, GroupResponse en ProblemDetails. Ze hebben publieke readonly properties, fromArray(), toArray() en JsonSerializable. De hydrateermethode valideert vereiste velden, scalartypes, lijsten, geneste objecten en datums. Rechtstreekse constructie van modellen gebruikt PHP-types; gebruik fromArray() voor validatie van externe data.

use Siteapps\OpenHoliday\Enum\HolidayType;

foreach ($holidays as $holiday) {
    if ($holiday->type === HolidayType::School) {
        // Schoolvakantie
    }

    $array = $holiday->toArray();
    $json = json_encode($holiday, JSON_THROW_ON_ERROR);
}

Bekende waarden worden HolidayType, RegionalScope of TemporalScope. Een toekomstige onbekende enumwaarde blijft een string, zodat een API-uitbreiding niet direct je applicatie breekt. Ontbrekende optionele velden worden null. Niet-nullable velden die expliciet null zijn, geven een decodeerfout.

toArray() laat properties met null weg, en bewaart false, 0 en lege lijsten. Onbekende responsevelden worden genegeerd. Bij ProblemDetails blijven extra velden juist bewaard in extensions, inclusief nullwaarden.

CSV, ICS en HTTP-metadata

Iedere getypeerde methode heeft een Response-variant met dezelfde parameters plus format. Die geeft Siteapps\OpenHoliday\Http\HttpResponse terug: statusCode, headers, body, getHeader() en getHeaderLine(). De body wordt bij deze variant niet gedecodeerd.

use Siteapps\OpenHoliday\Enum\ResponseFormat;

$calendar = $client->getPublicHolidaysResponse(
    countryIsoCode: 'NL',
    validFrom: '2026-01-01',
    validTo: '2026-12-31',
    languageIsoCode: 'NL',
    format: ResponseFormat::Calendar,
);
file_put_contents('feestdagen.ics', $calendar->body);

$csv = $client->getCountriesResponse(format: ResponseFormat::Csv);
file_put_contents('landen.csv', $csv->body);

$json = $client->getCountriesResponse();
echo $json->statusCode;
echo $json->getHeaderLine('Content-Type');

Calendar is beschikbaar op PublicHolidays en SchoolHolidays. Csv is beschikbaar op alle endpoints behalve de twee statistiekendpoints. Json, TextJson en PlainText zijn op alle endpoints beschikbaar. Een ongeldige combinatie geeft InvalidArgumentException voordat een request wordt verstuurd. HTTP-fouten worden ook bij de Response-varianten exceptions.

Configuratie

use Siteapps\OpenHoliday\Client;
use Siteapps\OpenHoliday\Configuration;

$client = new Client(new Configuration(
    baseUri: 'https://openholidaysapi.org',
    timeout: 30.0,
    connectTimeout: 10.0,
    userAgent: 'Workspace/1.0',
    headers: ['X-Request-ID' => 'my-request-id'],
));

De timeouts zijn in seconden. TLS-certificaten worden geverifieerd. Redirects worden niet automatisch gevolgd. Aanroepen zijn synchroon; caching en retries worden niet automatisch toegepast. Daardoor blijven verzoeken en eventuele herhalingen onder controle van de applicatie. Accept wordt bepaald door het gekozen responseformaat; User-Agent stel je in met de aparte optie.

Foutafhandeling

use Siteapps\OpenHoliday\Exception\ApiException;
use Siteapps\OpenHoliday\Exception\DecodingException;
use Siteapps\OpenHoliday\Exception\TransportException;

try {
    $countries = $client->getCountries('NL');
} catch (ApiException $exception) {
    // Elke niet-2xx status, inclusief 400, 429 en 500.
    $status = $exception->getStatusCode();
    $problem = $exception->problem; // ProblemDetails|null
    $rawBody = $exception->response->body;
    $retryAfter = $exception->response->getHeaderLine('Retry-After');
} catch (TransportException $exception) {
    // Bijvoorbeeld DNS-, TLS-, verbindings- of timeoutfout.
} catch (DecodingException $exception) {
    // Ongeldige JSON of een response die niet bij het verwachte model past.
    $response = $exception->response;
}

Deze drie exceptiontypes erven van OpenHolidayException. Ongeldige lokale argumenten gebruiken InvalidArgumentException. Een API-fout blijft een ApiException als de server HTML of een ongeldige ProblemDetails-body retourneert.

Eigen HTTP-client gebruiken

Implementeer Siteapps\OpenHoliday\Http\TransportInterface om bijvoorbeeld een bestaande Guzzle-, Symfony- of PSR-18-client te gebruiken. De interface heeft één methode: get(string $url, array $headers = []): HttpResponse.

$client = new Client(
    configuration: new Configuration(),
    transport: $yourTransport,
);

De transportadapter moet alle HTTP-statuscodes als HttpResponse teruggeven, ook 4xx/5xx. Alleen netwerkproblemen moeten TransportException opleveren. Headers zijn array<string, list<string>>, zodat herhaalde headers behouden blijven. De timeouts uit Configuration worden door het standaard cURL-transport gebruikt; stel timeouts bij een eigen transport zelf in. De Composer-eis voor ext-curl blijft ook bij een eigen adapter gelden.

Generieke endpointtoegang

use Siteapps\OpenHoliday\Enum\Endpoint;
use Siteapps\OpenHoliday\Enum\ResponseFormat;

$response = $client->request(
    Endpoint::SchoolHolidays,
    ['countryIsoCode' => 'NL', 'validFrom' => '2026-01-01', 'validTo' => '2026-12-31'],
    ResponseFormat::Json,
);

Deze methode controleert endpoint, parameternamen, verplichte parameters, datums en responseformaat. null-parameters worden weggelaten; lege optionele strings blijven behouden. Querystrings gebruiken RFC 3986-encoding.

Tests

composer lint              # PHP-syntaxcontrole
composer test              # Deterministische tests met fake transport; geen internet
composer test:transport    # Echte cURL-aanroepen naar een lokale PHP-testserver
composer check             # Alle drie bovenstaande controles
composer test:integration  # Optioneel: echte API-aanroepen naar alle 10 endpoints

De tests hebben geen PHPUnit of andere testdependencies nodig. De transporttest vereist CLI-PHP met proc_open en loopback-netwerktoegang. De GitHub Actions-workflow voert composer validate --strict, installatie en composer check uit op PHP 8.4. Zie VALIDATION.md voor de controles die bij deze oplevering zijn uitgevoerd en de beperkingen van de bouwomgeving.

Bron en licentie

De ingesloten openapi/openapi.json is de op 14 oktober 2026 uitgelezen OpenAPI 3.0.4-specificatie (API v1). De SDK maakt gebruik van de paden en schema's uit deze snapshot. Bij wijzigingen aan de API moeten SDK en snapshot samen worden bijgewerkt; dit package bevat geen generieke OpenAPI-generator.

De SDK-code heeft een MIT-licentie. De API-data en de overgenomen upstreammetadata behouden hun eigen licentie. Zie NOTICE.md.