https://github.com/andy87/php-client-sdk
Base abstractions for building typed PHP API clients.
https://github.com/andy87/php-client-sdk
Last synced: about 1 month ago
JSON representation
Base abstractions for building typed PHP API clients.
- Host: GitHub
- URL: https://github.com/andy87/php-client-sdk
- Owner: andy87
- Created: 2026-05-09T22:46:37.000Z (about 1 month ago)
- Default Branch: master
- Last Pushed: 2026-05-12T08:15:02.000Z (about 1 month ago)
- Last Synced: 2026-05-12T14:39:22.559Z (about 1 month ago)
- Language: PHP
- Homepage:
- Size: 240 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# PHP Client SDK
Base abstractions for building typed PHP API clients.
[Russian documentation](docs/ru/README.md)
## Overview
`andy87/php-client-sdk` provides a small set of reusable building blocks for API client SDKs:
- prompt DTOs for request method, endpoint, path parameters, query parameters, body and validation;
- response DTOs for normalized response data, status code, headers and API errors;
- provider base class for executing typed API methods;
- pluggable authorization strategies;
- pluggable HTTP transport with a native PHP stream implementation.
The package does not generate API clients and does not depend on a specific HTTP client library.
## Requirements
- PHP 8.1 or higher.
- Composer.
## Installation
```bash
composer require andy87/php-client-sdk
```
## Core Concepts
The package separates an API call into three parts:
- `PromptInterface` describes an outgoing request.
- `ResponseInterface` describes a typed API response.
- `AbstractProvider` connects prompts, responses, authorization and HTTP transport.
`NativeHttpTransport` can be used without extra dependencies. If a project needs another transport, implement `HttpTransportInterface`.
## Prompt DTO
Extend `AbstractPrompt` to describe a request. The base class hydrates declared properties from input data, validates required fields, builds path/query/body arrays and normalizes nested DTO values through `toArray()` or `toValue()` when those methods exist.
Use `PublicPrompt` for public endpoints and `PrivatePrompt` for private endpoints with an authorization profile. `AbstractPrompt` remains the generic base class for custom prompt schemes.
```php
'id',
'includePosts' => 'include_posts',
];
protected const REQUIRED_FIELDS = ['id'];
protected const PATH_FIELDS = ['id'];
protected const QUERY_FIELDS = ['includePosts'];
protected const BODY_FIELDS = [];
protected const CONTENT_TYPE = null;
public int $id;
public ?bool $includePosts = null;
}
```
```php
'id',
'name' => 'name',
];
protected const REQUIRED_FIELDS = ['id', 'name'];
public int $id;
public string $name;
}
```
## Provider Usage
Extend `AbstractProvider` and expose public methods for concrete API operations. The protected `request()` method validates the prompt, adds authorization headers when required, sends the HTTP request and returns the requested response DTO.
```php
request(
new GetUserPrompt(['id' => $id]),
GetUserResponse::class,
);
}
}
```
Create the provider with a base URL, authorization strategy and transport:
```php
getUser(123);
if ($response->hasError()) {
$error = $response->getError();
echo $error?->message ?? 'API request failed.';
}
echo $response->getStatusCode();
```
## Client Options
`ClientOptions` is the main extension point. If it is not passed, the SDK uses safe defaults: JSON requests and responses, strict successful response validation, native no-retry policy and default request factory.
Configurable parts:
- `timeout`, `headers`, `events`;
- `strictValidation`;
- `validatePrompt`;
- `retryPolicy`;
- `queryEncoder`;
- `bodyEncoder`;
- `responseDecoder`;
- `errorFactory`;
- `requestFactory`.
- `authorizationResolver`;
- `refreshAuthorizationStatusCodes`.
Retry is disabled by default. Use `DefaultRetryPolicy` only when repeated requests are safe for the target API operation.
`validatePrompt` controls local prompt validation before a request is built. It is enabled by default. Set it to `false` only in mock or test environments where a client must return success fixtures for incomplete input:
```php
'crm',
],
events: [
ClientEvents::BEFORE_REQUEST => static function (BeforeRequestEvent $event): void {
$event->request->headers['X-Trace-Id'] = bin2hex(random_bytes(8));
},
],
);
$runtime->addHeaders([
'X-Account' => 'main',
]);
```
Supported events:
- `ClientEvents::AFTER_INIT` after a concrete client finishes initialization.
- `ClientEvents::BEFORE_REQUEST` before transport sends a mutable `HttpRequest`.
- `ClientEvents::AFTER_REQUEST` after raw HTTP response is converted to a typed response DTO.
- `ClientEvents::REQUEST_EXCEPTION` after transport, JSON decoding or response DTO construction fails.
Header names are merged case-insensitively. Authorization headers override default runtime headers, and `BEFORE_REQUEST` listeners can still mutate the final request.
## Authorization
Use `NullAuthorizationStrategy` for public APIs:
```php
new ApiKeyAuthorizationStrategy('X-Api-Key', 'secret'),
]),
);
```
For `PrivatePrompt` subclasses, prefer profile names such as `default`, `avito-client-credentials`, `api-key` or `sandbox-token`:
```php
$options = new ClientOptions(
authorizationResolver: new AuthorizationProfileStrategyResolver([
'orders-api' => new ApiKeyAuthorizationStrategy('X-Api-Key', 'secret'),
]),
);
```
## HTTP Transport
`NativeHttpTransport` sends requests through PHP stream wrappers. It supports:
- query parameters;
- JSON request bodies;
- `application/x-www-form-urlencoded` request bodies;
- `multipart/form-data` request bodies through `MultipartFile`;
- already encoded raw request bodies;
- response status code and headers;
- JSON response decoding through `HttpResponse::json()`.
Custom transports must implement `HttpTransportInterface`:
```php
addJson('GET', '/users/{id}', [
'id' => 123,
'name' => 'Mock User',
]);
$provider = new UsersProvider(
baseUrl: 'https://api.example.com',
authorizationStrategy: new NullAuthorizationStrategy(),
transport: new MockTransport($resolver),
options: new ClientOptions(validatePrompt: false),
);
```
Routes match by HTTP method and absolute URL, path or endpoint template stored in request metadata. OAuth token requests can be mocked by absolute token URL:
```php
$resolver->addJson('POST', 'https://auth.example.com/oauth/token', [
'access_token' => 'mock-token',
'expires_in' => 3600,
]);
```
`validatePrompt=false` disables only `Prompt::validate()`. Request building can still fail when a prompt cannot provide a method, endpoint or required path placeholder.
If route paths are unstable or generated, use `PromptClassMockResponseResolver` to bind fixtures to Prompt DTO classes:
```php
addJson(GetUserPrompt::class, [
'id' => 123,
'name' => 'Mock User',
]);
$provider = new UsersProvider(
baseUrl: 'https://api.example.com',
authorizationStrategy: new NullAuthorizationStrategy(),
transport: new MockTransport($resolver),
);
```
## Traceable Transport
`TraceableTransport` wraps any `HttpTransportInterface` and records requests, responses, exceptions and duration without changing transport behavior.
```php
getUser(123);
$lastRecord = $transport->getLastRecord();
```
Response DTOs can also store local diagnostic notes:
```php
$response->addDiagnostic(['source' => 'fixture', 'case' => 'empty-list']);
$diagnostics = $response->getDiagnostics();
```
## Error Handling
- Prompt validation throws `InvalidArgumentException` when a required field is missing or empty.
- Request factory validation can throw `ValidationException` when an endpoint contains an unfilled path placeholder.
- Authorization failures throw `AuthorizationException`.
- Transport failures throw `TransportException`.
- Successful non-JSON responses throw `ResponseDecodeException`.
- Response DTO construction failures throw `ResponseHydrationException`.
- HTTP responses with status code `400` or higher are converted to `ApiError` and available through `ResponseInterface::getError()`, including non-JSON error bodies.
- Successful responses with missing required fields throw `UnexpectedValueException` when `strictValidation` is enabled.
## License
MIT.