php-openapi-generator

Client Generation

Use GenerationTarget::Client to generate typed API client classes from paths plus DTO models from components/schemas.

This keeps API client generation in a PHP-native workflow: no npm-based generators required.

What Gets Generated

For each API group, the generator creates:

Typical output:

generated/
|- Api/
|  |- PetsApiClientInterface.php
|  `- PetsApiClient.php
`- Model/
   |- Pet.php
   |- NewPet.php
   `- ...

Basic Configuration

<?php

declare(strict_types=1);

use MaxBeckers\OpenApiGenerator\Config\GenerationTarget;
use MaxBeckers\OpenApiGenerator\Config\GeneratorConfig;
use MaxBeckers\OpenApiGenerator\Config\HttpClientAdapter;

$config = new GeneratorConfig();

$config->specFile = 'openapi.yaml';
$config->outputDir = 'generated';
$config->generationTarget = GenerationTarget::Client;
$config->httpClient = HttpClientAdapter::SymfonyHttpClient;

$config->modelNamespace = 'App\\Model';
$config->apiNamespace = 'App\\Api';

return $config;

Runtime Shape of Generated Clients

Generated client methods usually follow this flow:

  1. Build URL from baseUrl (trailing slashes are trimmed) and URL-encoded path values.
  2. Build the query string and body payload from typed inputs.
  3. Execute HTTP request with selected adapter.
  4. Decode the JSON response and map it back into generated DTOs via fromResponseArray().

Shared behavior:

Authentication

With $config->generateSecuritySchemes = true (default), components.securitySchemes are applied to operations. An ApiCredentials class is generated next to the clients, and clients whose operations are secured accept it as an optional last constructor argument:

$client = new PetsApiClient($httpClient, 'https://api.example.com', credentials: new ApiCredentials(
    bearerAuthToken: $token,        // http bearer, oauth2, openIdConnect: {scheme}Token
    basicAuthUsername: 'user',      // http basic: {scheme}Username / {scheme}Password
    basicAuthPassword: 'secret',
    apiKey: 'key',                  // apiKey (header, query or cookie): {scheme}
));

Operation-level security overrides the global requirement and security: [] disables authentication. For each request, the first requirement alternative whose credentials are all set is applied; if none matches (or {} is listed), the request is sent without credentials.

Typed Error Responses

With $config->typedErrorResponses = true, non-2xx responses throw {apiNamespace}\Exception\ApiException (a RuntimeException) or a subclass per documented status code, such as NotFoundException or UnprocessableEntityException (Http{code}Exception for codes without a standard reason phrase). The exception exposes statusCode, operationId, responseBody and payload. When the error response documents a JSON model (by exact code, 4XX/5XX range or default), payload is the hydrated model; otherwise it is the decoded JSON or null.

try {
    $client->getPet('42');
} catch (NotFoundException $exception) {
    $problem = $exception->payload; // e.g. Problem model
}

Choosing an HTTP Adapter

See HTTP Client Adapters for concrete adapter examples.

Optional Validation Hooks

If enabled in config, generated clients can validate request and response DTOs around HTTP calls.

See Validation Strategies.