The openai-php/client is the official PHP library for the OpenAI API. It covers chat completions, streaming, embeddings, image generation, audio transcription, and more. This guide walks through every major feature with complete, runnable code examples.
If you’re using Laravel, see How to Integrate OpenAI API with Laravel for a framework-specific guide. For a basic PHP setup, see OpenAI PHP Tutorial.
Installation
composer require openai-php/clientRequirements: PHP 8.1+, Composer. The package requires the php-http/discovery package for HTTP transport, which is installed automatically.
Initialization
<?php
require 'vendor/autoload.php';
$client = OpenAI::client(getenv('OPENAI_API_KEY'));Set your API key as an environment variable:
export OPENAI_API_KEY=sk-proj-...Chat Completions
The most common use case — send messages and get a response:
$response = $client->chat()->create([
'model' => 'gpt-4o-mini',
'messages' => [
['role' => 'system', 'content' => 'You are a helpful assistant.'],
['role' => 'user', 'content' => 'What is the capital of France?'],
],
]);
echo $response->choices[0]->message->content;
// ParisMulti-Turn Conversations
Build a conversation by appending each exchange to the messages array:
$messages = [
['role' => 'system', 'content' => 'You are a helpful assistant.'],
];
function chat(array &$messages, string $input, $client): string
{
$messages[] = ['role' => 'user', 'content' => $input];
$response = $client->chat()->create([
'model' => 'gpt-4o-mini',
'messages' => $messages,
]);
$reply = $response->choices[0]->message->content;
$messages[] = ['role' => 'assistant', 'content' => $reply];
return $reply;
}
echo chat($messages, 'My name is Alex.', $client); // Nice to meet you, Alex!
echo chat($messages, 'What is my name?', $client); // Your name is Alex.Streaming Responses
Stream tokens as they are generated — ideal for chat UIs:
$stream = $client->chat()->createStreamed([
'model' => 'gpt-4o-mini',
'messages' => [
['role' => 'user', 'content' => 'Write a short poem about PHP.'],
],
]);
foreach ($stream as $response) {
$delta = $response->choices[0]->delta->content;
if ($delta !== null) {
echo $delta;
ob_flush();
flush();
}
}For a web-based streaming UI with SSE, see How to Build an AI Chatbot with PHP.
Function Calling / Tool Use
Define tools that the model can call:
$response = $client->chat()->create([
'model' => 'gpt-4o-mini',
'messages' => [
['role' => 'user', 'content' => "What's the weather in Kyiv?"],
],
'tools' => [
[
'type' => 'function',
'function' => [
'name' => 'get_weather',
'description' => 'Get current weather for a city',
'parameters' => [
'type' => 'object',
'properties' => [
'city' => ['type' => 'string', 'description' => 'City name'],
],
'required' => ['city'],
],
],
],
],
'tool_choice' => 'auto',
]);
$message = $response->choices[0]->message;
if ($message->toolCalls) {
foreach ($message->toolCalls as $toolCall) {
$name = $toolCall->function->name;
$args = json_decode($toolCall->function->arguments, true);
// Execute your function here: call_weather_api($args['city'])
echo "Model wants to call: $name with args: " . json_encode($args);
}
}Text Embeddings
Convert text into vectors for semantic search or RAG:
$response = $client->embeddings()->create([
'model' => 'text-embedding-3-small',
'input' => 'Laravel is a PHP framework for web artisans.',
]);
$vector = $response->embeddings[0]->embedding;
// 1536-dimensional float array
// Batch embeddings
$response = $client->embeddings()->create([
'model' => 'text-embedding-3-small',
'input' => ['First text', 'Second text', 'Third text'],
]);
foreach ($response->embeddings as $embedding) {
// $embedding->embedding — vector
// $embedding->index — position in input array
}Image Generation (DALL·E)
// Generate image
$response = $client->images()->create([
'model' => 'dall-e-3',
'prompt' => 'A futuristic PHP elephant mascot',
'n' => 1,
'size' => '1024x1024',
'quality' => 'standard',
]);
$imageUrl = $response->data[0]->url;
echo $imageUrl; // https://oaidalleapiprodscus.blob.core.windows.net/...
// Edit an existing image (requires mask)
$response = $client->images()->edit([
'image' => fopen('original.png', 'r'),
'mask' => fopen('mask.png', 'r'),
'prompt' => 'Add a rainbow in the background',
'n' => 1,
'size' => '1024x1024',
]);Audio Transcription (Whisper)
$response = $client->audio()->transcribe([
'model' => 'whisper-1',
'file' => fopen('audio.mp3', 'r'),
]);
echo $response->text;
// The transcribed text from the audio file
// Translate non-English audio to English
$response = $client->audio()->translate([
'model' => 'whisper-1',
'file' => fopen('french_audio.mp3', 'r'),
]);Moderation
Check if content violates OpenAI usage policies:
$response = $client->moderations()->create([
'input' => $userMessage,
]);
$result = $response->results[0];
if ($result->flagged) {
$categories = array_filter((array) $result->categories);
echo "Flagged categories: " . implode(', ', array_keys($categories));
} else {
echo "Content is safe";
}Error Handling
Always handle API errors in production:
use OpenAI\Exceptions\ErrorException;
use OpenAI\Exceptions\TransporterException;
use OpenAI\Exceptions\UnserializableResponse;
try {
$response = $client->chat()->create([
'model' => 'gpt-4o-mini',
'messages' => [['role' => 'user', 'content' => $input]],
]);
return $response->choices[0]->message->content;
} catch (ErrorException $e) {
// 400 Bad Request, 401 Unauthorized, 429 Rate Limit, 500 Server Error
$code = $e->getCode();
if ($code === 429) {
// Rate limited — implement exponential backoff
sleep(2);
// retry...
}
throw new RuntimeException("OpenAI error [{$code}]: " . $e->getMessage());
} catch (TransporterException $e) {
// Network timeout, DNS failure, etc.
throw new RuntimeException("Network error: " . $e->getMessage());
} catch (UnserializableResponse $e) {
// Unexpected response format
throw new RuntimeException("Invalid response: " . $e->getMessage());
}Configuration Options
Customise the client with a factory:
$client = OpenAI::factory()
->withApiKey(getenv('OPENAI_API_KEY'))
->withOrganization('org-...') // optional
->withBaseUri('https://api.openai.com/v1')
->withHttpClient(new \GuzzleHttp\Client(['timeout' => 30]))
->withHttpHeader('X-Custom-Header', 'value')
->make();Listing Models
$models = $client->models()->list();
foreach ($models->data as $model) {
echo $model->id . "\n";
}
// gpt-4o, gpt-4o-mini, gpt-3.5-turbo, text-embedding-3-small, ...
// Get a single model
$model = $client->models()->retrieve('gpt-4o-mini');
echo $model->ownedBy; // openaiSummary
composer require openai-php/client— install the SDK- Chat:
$client->chat()->create()— supports system/user/assistant roles - Streaming:
$client->chat()->createStreamed()— iterate over token chunks - Embeddings:
$client->embeddings()->create()— returns float vectors - Images:
$client->images()->create()— DALL·E 3 generation - Audio:
$client->audio()->transcribe()— Whisper transcription - Errors: catch
ErrorException,TransporterException,UnserializableResponse
Subscribe to my newsletter — practical guides on Claude API, AI agents, RAG, and automation.