microsoft/kiota-abstractions
Core PHP abstractions required by Kiota-generated SDKs from OpenAPI. Provides the base constructs used by generated clients to build and run. Install via Composer and reference from Kiota PHP projects.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require microsoft/kiota-abstractions
This package is a dependency for Kiota-generated SDKs, so you typically won’t use it directly unless extending or customizing Kiota functionality.
First Use Case:
RequestInformation, ApiException).BackedModel, ParseNode).AccessTokenProvider).RequestAdapter).use Microsoft\Kiota\Abstractions\RequestInformation;
use Microsoft\Kiota\Abstractions\RequestAdapter;
$requestInfo = new RequestInformation();
$requestInfo->method = 'GET';
$requestInfo->urlTemplate = 'https://api.example.com/users/{id}';
$requestInfo->pathParameters = ['id' => '123'];
$adapter = new RequestAdapter();
$response = $adapter->sendAsync($requestInfo)->wait();
Key Classes to Explore:
RequestInformation: Core request metadata (headers, body, URL templates).BackedModel: Base class for generated models (handles serialization/deserialization).ApiException: Standardized error handling for API responses.RequestAdapter: Interface for HTTP clients (e.g., Guzzle, Symfony HTTP Client).$requestInfo = new RequestInformation();
$requestInfo->headers->add('X-Custom-Header', 'value');
$requestInfo->headers->tryAdd('X-Idempotency', 'unique-id'); // Safe add (no overwrite)
$requestInfo->setStreamContent(
fopen('file.txt', 'r'),
'application/octet-stream' // Defaults to this if omitted
);
BackedModel for custom logic:
use Microsoft\Kiota\Abstractions\BackedModel;
class CustomUser extends BackedModel {
public string $name;
public int $age;
protected function getFieldDeserializers(): array {
return [
'name' => fn($value) => $value,
'age' => fn($value) => (int)$value,
];
}
}
$user = new CustomUser();
$user->address->city = 'New York'; // Triggers dirty state
AccessTokenProvider for OAuth/JWT:
use Microsoft\Kiota\Abstractions\AccessTokenProvider;
class MyTokenProvider implements AccessTokenProvider {
public function getAuthorizationTokenAsync(): ?string {
return 'Bearer ' . $this->fetchToken();
}
}
$requestInfo->accessTokenProvider = new MyTokenProvider();
use Microsoft\Kiota\Abstractions\RequestAdapter;
use GuzzleHttp\Client;
class GuzzleAdapter implements RequestAdapter {
private Client $client;
public function sendAsync(RequestInformation $requestInfo): Promise {
return new Promise(fn() => $this->client->request(
$requestInfo->method,
$requestInfo->url,
[
'headers' => $requestInfo->headers->toArray(),
'body' => $requestInfo->body,
]
));
}
}
ApiException for HTTP errors:
try {
$response = $adapter->sendAsync($requestInfo)->wait();
} catch (ApiException $e) {
// Access status code, headers, or body
$status = $e->statusCode;
$headers = $e->headers;
}
use Microsoft\Kiota\Abstractions\Observability\Telemetry;
Telemetry::setTracerProvider($tracerProvider);
std-uritemplate for dynamic URLs:
$requestInfo->urlTemplate = '/users/{id}/posts/{postId}';
$requestInfo->pathParameters = ['id' => '1', 'postId' => '42'];
// Resolves to: /users/1/posts/42
PHP Version Requirement:
^1.5.0).Nullability:
AccessTokenProvider::getAuthorizationTokenAsync() return ?string. Always handle null:
$token = $provider->getAuthorizationTokenAsync();
if ($token === null) {
throw new RuntimeException('Token provider failed');
}
Dirty State in Nested Models:
BackedModel or array of models marks the entire parent model as dirty. Avoid deep nesting if performance is critical.Header Case Sensitivity:
tryAdd() to avoid overwriting existing headers accidentally.Deprecated Methods:
ApiException::getResponse() was removed in v0.6.0. Use statusCode, headers, or body directly.Stream Content Defaults:
setStreamContent() defaults to application/octet-stream. Specify explicitly for non-binary data (e.g., text/plain).OpenTelemetry Auto-Suggestion:
Inspect Requests:
RequestInformation before sending:
var_dump($requestInfo->url, $requestInfo->headers->toArray(), $requestInfo->body);
Validate Models:
BackedModel::validate() to check deserialized data:
if (!$model->validate()) {
throw new InvalidArgumentException('Model validation failed');
}
URL Template Errors:
pathParameters match the template exactly (e.g., {id} vs. {userId}).Async Promises:
->wait() for synchronous code or then() for async:
$adapter->sendAsync($requestInfo)
->then(fn($response) => $response->body)
->otherwise(fn($e) => error_log($e->getMessage()));
Custom Serializers/Deserializers:
getFieldSerializers()/getFieldDeserializers() in BackedModel subclasses.Request Middleware:
RequestAdapter to add logging, retries, or auth:
class LoggingAdapter implements RequestAdapter {
private RequestAdapter $delegate;
public function sendAsync(RequestInformation $requestInfo): Promise {
error_log('Sending request to: ' . $requestInfo->url);
return $this->delegate->sendAsync($requestInfo);
}
}
Composed Types:
ComposedTypeWrapper for proper deserialization.Date/Time Handling:
DateTimeHelper, DateIntervalHelper) for ISO 8601 parsing/formatting.Multipart Requests:
RequestInformation::setMultipartContent() for file uploads:
$requestInfo->setMultipartContent([
'file' => new \CURLFile('path/to/file'),
'data' => 'value',
]);
Backing Store Factory:
BackingStoreFactorySingleton) is non-nullable since v0.6.0. No need to check for null.Default Content Types:
setStreamContent() defaults to application/octet-stream. Override if needed (e.gHow can I help you explore Laravel packages today?