openai-php/client
Community-maintained PHP client for the OpenAI API. Install via Composer and interact with models, responses, chat, images, audio, files, and more with a clean, typed interface—ideal for Laravel and modern PHP apps.
## Getting Started
### Minimal Setup
1. **Installation**: Add the package via Composer:
```bash
composer require openai-php/client guzzlehttp/guzzle
(Note: guzzlehttp/guzzle is required for HTTP requests if not already present in your project.)
First API Call: Initialize the client with your OpenAI API key (preferably from .env):
$client = OpenAI::client(env('OPENAI_API_KEY'));
Basic Usage: Use the responses resource for chat completions (OpenAI's modern API):
$response = $client->responses()->create([
'model' => 'gpt-4o-mini',
'input' => 'Hello! How are you?',
]);
echo $response->outputText; // Assistant's reply
Key Resources: Focus on these for 80% of use cases:
responses() → Chat completions (replaces chat in older APIs).models() → List/retrieve available models.files() → Upload/delete files for fine-tuning or assistants.Wrap the client in a Laravel service class to abstract API calls and handle errors:
// app/Services/OpenAIService.php
class OpenAIService {
public function __construct(private OpenAI $client) {}
public function generateResponse(string $prompt, string $model = 'gpt-4o-mini'): string {
try {
$response = $this->client->responses()->create([
'model' => $model,
'input' => $prompt,
'temperature' => 0.7,
]);
return $response->outputText;
} catch (\OpenAI\Exceptions\OpenAIException $e) {
Log::error('OpenAI API Error: ' . $e->getMessage());
throw new \RuntimeException('Failed to generate response.');
}
}
}
Register in AppServiceProvider:
public function register() {
$this->app->singleton(OpenAIService::class, fn() => new OpenAIService(
OpenAI::client(env('OPENAI_API_KEY'))
));
}
Useful for real-time applications (e.g., chat apps):
$stream = $client->responses()->createStreamed([
'model' => 'gpt-4o-mini',
'input' => 'Explain Laravel middleware...',
]);
foreach ($stream as $chunk) {
if ($chunk->event === 'response.delta') {
echo $chunk->delta->content[0]->text; // Stream output incrementally
}
}
For custom function integration:
$response = $client->responses()->create([
'model' => 'guzzlehttp/guzzle',
'tools' => [
[
'type' => 'function',
'name' => 'fetch_weather',
'parameters' => [
'type' => 'object',
'properties' => [
'city' => ['type' => 'string'],
],
'required' => ['city'],
],
],
],
'input' => 'What’s the weather in Barcelona?',
]);
// Handle function calls
foreach ($response->output as $output) {
if ($output->type === 'function_call' && $output->name === 'fetch_weather') {
$args = json_decode($output->arguments, true);
$weather = $this->fetchWeatherFromExternalService($args['city']);
// Return result to OpenAI (not shown; requires follow-up API call)
}
}
Store context across messages:
// Start a conversation
$conv = $client->conversations()->create([
'metadata' => ['user_id' => auth()->id()],
'items' => [['role' => 'system', 'content' => 'You are a helpful assistant.']],
]);
// Add a user message
$client->conversations()->items()->create($conv->id, [
'items' => [['role' => 'user', 'content' => 'Hi!']],
]);
// Get assistant response
$response = $client->responses()->create([
'model' => 'gpt-4o-mini',
'input' => 'Hi!',
'previous_response_id' => $conv->lastMessageId, // Link to conversation
]);
Upload a file for fine-tuning:
$file = $client->files()->upload(
'file-abc123.pdf',
fopen('path/to/file.pdf', 'r'),
'application/pdf'
);
// Use the file ID in fine-tuning or assistants
$fineTune = $client->fineTunes()->create([
'training_file' => 'file-abc123',
'model' => 'gpt-3.5-turbo',
]);
Centralize error handling in a middleware or service:
// app/Exceptions/Handler.php
public function render($request, Throwable $exception) {
if ($exception instanceof \OpenAI\Exceptions\OpenAIException) {
return response()->json([
'error' => 'openai_api_error',
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
], 429); // Rate limit or API error
}
return parent::render($request, $exception);
}
Use Laravel’s config to manage API settings:
// config/openai.php
return [
'api_key' => env('OPENAI_API_KEY'),
'base_uri' => env('OPENAI_BASE_URI', 'https://api.openai.com/v1'),
'default_model' => 'gpt-4o-mini',
'timeout' => 30,
];
// In a service:
$client = OpenAI::factory()
->withApiKey(config('openai.api_key'))
->withBaseUri(config('openai.base_uri'))
->make();
.env and Laravel’s env() helper.gpt-4o models.gpt-3.5-turbo.use OpenAI\Exceptions\RateLimitException;
try {
$response = $client->responses()->create([...]);
} catch (RateLimitException $e) {
sleep($e->getRetryAfter()); // Respect the `retry-after` header
retry();
}
$buffer = '';
foreach ($stream as $chunk) {
$buffer .= $chunk->delta->content[0]->text ?? '';
if (str_ends_with($buffer, ['.', '!', '?'])) {
echo $buffer . "\n";
$buffer = '';
}
}
$client = OpenAI::factory()
->withHttpClient(new \GuzzleHttp\Client(['timeout' => 120]))
->make();
responses() for GPT-4o, chat() for legacy GPT-3.5 (deprecated).gpt-4o-mini is cheaper but less capable than gpt-4o. Log token usage:
$usage = $response->usage;
Log::info("Tokens used: {$usage->inputTokens} (input), {$usage->outputTokens} (output)");
function_call, you must:
responses()->create with the previous_response_id).$response = $client->responses()->create([...]);
foreach ($response->output as $output) {
if ($output->type === 'function_call') {
$result = $this->executeFunction($output->name,
How can I help you explore Laravel packages today?