Claude PHP SDKの値オブジェクトとバージョン運用
PHP 8.1以上向け公式SDKの導入・Value Object・PSR-18ストリーミング・エラー処理・SemVer運用まで実装例で解説します。
PHP SDKの導入 — インストールと動作要件
Anthropic公式のPHP SDKは、PHP 8.1.0以上のアプリケーションからClaude APIへアクセスするためのライブラリです。HTTP通信はPSR-18に準拠し、インストール済みのPSR-18クライアントを自動で探しに行きます。公式が推奨するのはGuzzleで、追加設定なしにストリーミング向けの構成が入るためです。
このSDKが担うのは、リクエストを組み立てて送り、応答を受け取るところまでです。ツール実行結果を踏まえて次の一手を自律的に判断し続けるようなエージェントの実行基盤そのものは含みません。そうした自律エージェントの構築はPython・TypeScript向けのAgent SDKやClaude Codeの領分です。Laravelのジョブキューや既存のPHPアプリケーションの一機能としてClaudeを呼び出すような、必要なタイミングでリクエストを送る構成にはPHP SDKが向いています。HTTP層にはPSR-18という標準インターフェースを採用しています。そのぶん、LaravelのHTTPクライアント設定やSymfonyのHttpClientコンポーネントなど、フレームワーク側で既に用意されているPSR-18実装をそのまま流用しやすい構成になっています。
インストール済みのPSR-18クライアントは自動で検出されるため、開発者が明示的に配線コードを書く必要はありません。ただしどのPSR-18実装が検出されるかによってストリーミングの挙動が変わります。複数のHTTPクライアントを併用しているプロジェクトでは、意図しないクライアントが優先されていないかを確認しておく価値があります。
composer require "anthropic-ai/sdk" "guzzlehttp/guzzle:^7"このSDKは名前付き引数(named arguments)を前提に設計されており、デフォルト値を持つパラメータは名前を指定して渡す必要があります。
$client = new Client();
$message = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Hello, Claude']],
model: 'claude-opus-5',
);
$textBlock = array_find($message->content, static fn ($block): bool => $block->type === 'text');
echo $textBlock->text;APIキーは環境変数から自動で読み込まれます。Workload Identity Federationのような他の認証方式にも対応しています。個人アカウントキーやサービスアカウントキーが複数のワークスペースにアクセスできる場合は、リクエストヘッダー anthropic-workspace-id でワークスペースを明示します。明示しないまま複数ワークスペース対応のキーを使うと、意図しないワークスペースの利用量として計上されることがあります。請求管理の観点でも見落とせない設定です。
Value Objectをstaticコンストラクタとビルダーの両方で組み立てる
PHP SDKの値オブジェクトは、静的コンストラクタ with を名前付き引数と組み合わせて初期化するのが推奨パターンです。同じ結果をビルダー形式で組み立てることもでき、既存コードのスタイルに合わせて選べます。
// 推奨: staticコンストラクタ + 名前付き引数
Base64ImageSource::with(data: "U3RhaW5sZXNzIHJvY2tz", ...);
// 代替: ビルダー
(new Base64ImageSource)->withData("U3RhaW5sZXNzIHJvY2tz");リクエストオプションも同じ with パターンで組み立てます。Anthropic\RequestOptions::with(...) には maxRetries や timeout、後述の streamingTransporter を渡せます。この書き方が全体で統一されているため、一度覚えればクライアント設定・リトライ設定・ストリーミング設定のすべてに応用できます。
with 静的コンストラクタとビルダーの2形式が両方用意されている理由は、初期化のスタイルをプロジェクトの既存コードに合わせられるようにするためです。すでにビルダーパターンを多用しているコードベースなら withData() のような連鎖呼び出しに揃えられます。関数型寄りの書き方を好むなら with(...) に名前付き引数を渡す形で完結させられます。どちらの形式で組み立てても最終的に得られるオブジェクトの種類は同じです。チームのコーディング規約に応じて統一すれば十分です。
ストリーミングとPSR-18クライアントの相性
Server-Sent Eventsによるストリーミングは messages->createStream で扱います。
$client = new Client();
$stream = $client->messages->createStream(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Hello, Claude']],
model: 'claude-opus-5',
);
foreach ($stream as $event) {
echo $event->type . PHP_EOL;
}ストリーミングが機能するには、レスポンスボディを段階的に返すHTTPクライアントが必要です。Guzzleが検出されている場合はSDK側で自動的にストリーミング向けに構成されます。バッファリング型のクライアントだと foreach ループがレスポンス完了時に全イベントをまとめて返してしまいます。この症状が出た場合は、Guzzleを導入するか streamingTransporter リクエストオプションでストリーミング対応のPSR-18クライアントを明示的に渡してください。
$client = new Anthropic\Client(
requestOptions: Anthropic\RequestOptions::with(streamingTransporter: $myStreamingClient),
);エラー処理・リトライ・ページネーション
接続に失敗した場合やAPIが4xx/5xx応答を返した場合、Anthropic\Core\Exceptions\APIException のサブクラスが投げられます。
use Anthropic\Core\Exceptions\APIConnectionException;
use Anthropic\Core\Exceptions\RateLimitException;
use Anthropic\Core\Exceptions\APIStatusException;
try {
$message = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Hello, Claude']],
model: 'claude-opus-5',
);
} catch (APIConnectionException $e) {
echo "サーバーに接続できませんでした", PHP_EOL;
} catch (RateLimitException $_) {
echo "429を受信しました。少し待ってから再試行します", PHP_EOL;
} catch (APIStatusException $e) {
echo "200番台以外のステータスを受信しました: " . $e->getMessage();
}ステータスコードと例外クラスの対応は次の通りです。
| ステータス | 例外クラス |
|---|---|
| HTTP 400 | 例外クラスBadRequestException |
| HTTP 401 | 例外クラスAuthenticationException |
| HTTP 403 | 例外クラスPermissionDeniedException |
| HTTP 404 | 例外クラスNotFoundException |
| HTTP 409 | 例外クラスConflictException |
| HTTP 422 | 例外クラスUnprocessableEntityException |
| HTTP 429 | 例外クラスRateLimitException |
| HTTP 500以上 | 例外クラスInternalServerException |
| 上記以外のHTTPエラー | 例外クラスAPIStatusException |
| タイムアウト | 例外クラスAPITimeoutException |
| ネットワークエラー | 例外クラスAPIConnectionException |
接続エラー・408・409・429・500番台・タイムアウトは、デフォルトで2回まで短い指数バックオフとともに自動リトライされます。maxRetries を RequestOptions::with() に渡せば、クライアント全体またはリクエスト単位で回数を変更できます。maxRetries: 0 を指定すればリトライ自体を無効化することもでき、冪等でない処理を呼び出す場合に有効です。
一覧取得系のエンドポイントはページネーションされており、SDKは自動でページを進めるイテレータを提供します。
$client = new Client();
$page = $client->beta->messages->batches->list(limit: 20);
// 現在のページのアイテムを取得
foreach ($page->getItems() as $item) {
echo $item->id, PHP_EOL;
}
// 現在のページ以降、すべてのページを自動取得
foreach ($page->pagingEachItem() as $item) {
echo $item->id, PHP_EOL;
}Bedrock・Agent Platform・AWS・Foundryへのプラットフォーム統合
PHP SDKは4つのクラウドプラットフォームに対応しています。
| プラットフォーム | クライアント | 備考 |
|---|---|---|
| Agent Platform | クライアントAnthropic\Vertex\Client | 備考::fromEnvironment() で生成 |
| Bedrock(新規) | クライアントAnthropic\Bedrock\MantleClient | 備考new MantleClient(awsRegion: ...) |
| Bedrock(既存) | クライアントAnthropic\Bedrock\Client | 備考InvokeModel API利用アプリ向け |
| Claude Platform on AWS | クライアントAnthropic\Aws\Client | 備考aws/aws-sdk-php がソフト依存。ベータ |
| Foundry | クライアントAnthropic\Foundry\Client | 備考::withCredentials() で生成 |
新規プロジェクトは MantleClient を使い、Anthropic\Bedrock\Client は既存の InvokeModel API利用アプリの後方互換用として残されています。Claude Platform on AWSはワークスペースIDをコンストラクタか環境変数 ANTHROPIC_AWS_WORKSPACE_ID で指定するベータ機能です。どのプラットフォームを選ぶかは、すでに利用しているクラウドインフラとの兼ね合いで決まります。単体でAPIキーを発行して使う構成とは、認証・請求の経路が別になる点に注意してください。
未文書化のエンドポイント・パラメータへのアクセス
ドキュメントに載っていないパラメータの送信や、未文書化のレスポンスプロパティの読み取りも RequestOptions::with() の extraQueryParams ・extraBodyParams ・extraHeaders で行えます。
$message = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Hello, Claude']],
model: 'claude-opus-5',
requestOptions: RequestOptions::with(
extraQueryParams: ['my_query_parameter' => 'value'],
extraBodyParams: ['my_body_parameter' => 'value'],
extraHeaders: ['my-header' => 'value'],
),
);未文書化のエンドポイントそのものを叩きたい場合は $client->request(...) を使うと、認証やリトライなどクライアントの機能を維持したままリクエストできます。
$client = new Client();
$response = $client->request(
method: "post",
path: '/undocumented/endpoint',
query: ['dog' => 'woof'],
headers: ['useful-header' => 'interesting-value'],
body: ['hello' => 'world']
);PHP SDKの実装上の癖
PHP SDKはベータ版で、メジャーバージョンが0のあいだはAPIが変わりえます。Composerでのバージョン固定と、更新時のリリースノート確認が欠かせません。破壊的変更が入った場合の影響範囲を、導入時点であらかじめ見積もっておくと安心です。なお、実行時の挙動に影響しないPHPDocの型定義の改善は、破壊的変更として扱われません。
もう一つの癖は名前付き引数への依存度の高さです。PHP SDKはデフォルト値付きパラメータを名前指定必須にすることで、位置引数の順序違いによる事故を型システムレベルで防いでいます。値オブジェクトの with コンストラクタパターンも同じ思想の延長です。コンストラクタの引数順を覚える必要がありません。
裏を返すと、PHP 8.1.0未満をサポートしなければならない既存プロジェクトでは、このSDKをそのまま導入できません。名前付き引数を多用する設計である以上、レガシーなPHPバージョンへの後方対応は現実的な選択肢として提示されていません。
よくあるつまずき
- ストリーミングがイベントを一括で返す: バッファリング型のPSR-18クライアントを使っていると発生します。多くの場合はGuzzleが未導入か、別のPSR-18実装が優先的に検出されていることが原因なので、Guzzleの導入か
streamingTransporterの明示指定で解決します - 名前付き引数の書き忘れ: デフォルト値のあるパラメータを位置引数で渡そうとするとエラーになります。
create()などの呼び出しは基本的にすべて名前付きで書く前提なので、他言語のコード例をそのまま移植する際に見落としがちです - BedrockClientとMantleClientの取り違え: 新規実装は
MantleClientが前提で、Bedrock\Clientは既存のInvokeModelAPI利用アプリのための後方互換クライアントです。どちらを使うべきか迷ったら、新規プロジェクトかどうかで判断します - ベータ版であることの見落とし: メジャーバージョン0の間は破壊的変更が入りうるため、Composerでバージョンを固定せずに
^0のような緩い制約で運用するのはリスクがあります。CI環境でのビルドが突然壊れる原因の多くはこのパターンです
まとめ
PHP SDKは composer require "anthropic-ai/sdk" "guzzlehttp/guzzle:^7" で導入でき、PHP 8.1.0以上が前提条件です。値オブジェクトは with コンストラクタと名前付き引数の組み合わせが基本形で、ストリーミングを使うならGuzzleの導入がほぼ必須になります。ベータ版であるあいだは、本番運用でのバージョン固定と更新時の確認が重要です。
料金・モデル選択・認証まわりの全体像はAnthropic API完全ガイド、コスト最適化の観点ではAnthropic APIのPrompt Cachingを理解する、自律的にツールを連鎖実行するエージェントを組む場合はAgent SDKクイックスタートもあわせて参照してください。