openai-php/laravel
Community-maintained OpenAI PHP integration for Laravel. Install via Composer and artisan, configure API key in .env, then use the OpenAI facade to call OpenAI endpoints (e.g., Responses API) from your Laravel app.
composer require openai-php/laravel
config/openai.php and updates .env):
php artisan openai:install
.env with your OpenAI credentials:
OPENAI_API_KEY=sk-your-key
OPENAI_ORGANIZATION=org-your-org
responses facade):
use OpenAI\Laravel\Facades\OpenAI;
$response = OpenAI::responses()->create([
'model' => 'gpt-3.5-turbo',
'messages' => [['role' => 'user', 'content' => 'Hello!']],
]);
echo $response->choices[0]->message->content;
OpenAI::responses(), OpenAI::chat(), OpenAI::completions(), etc.config/openai.php (timeout, base URL, etc.)OpenAI::fake() for mocking responses.// Single request
$response = OpenAI::chat()->create([
'model' => 'gpt-4',
'messages' => [
['role' => 'system', 'content' => 'You are a helpful assistant.'],
['role' => 'user', 'content' => 'Explain Laravel middleware.'],
],
]);
// Streamed response (for real-time UX)
$response = OpenAI::chat()->create([
'model' => 'gpt-3.5-turbo',
'messages' => [...],
'stream' => true,
]);
foreach ($response as $chunk) {
echo $chunk->choices[0]->delta->content;
}
$response = OpenAI::chat()->create([
'model' => 'gpt-3.5-turbo-0613',
'messages' => [...],
'response_format' => ['type' => 'json_object'],
]);
$data = json_decode($response->choices[0]->message->content, true);
use OpenAI\Resources\Chat;
$response = OpenAI::chat()->create([
'model' => 'gpt-4',
'messages' => [...],
'stream' => false,
]);
// Store $response->id for later retrieval
$job = new ProcessOpenAIResponse($response->id);
dispatch($job);
try {
$response = OpenAI::chat()->create([...]);
} catch (\OpenAI\Exceptions\RateLimitException $e) {
// Retry with exponential backoff
sleep(2 ** $e->getRetryAfter());
retry();
} catch (\OpenAI\Exceptions\InvalidRequestException $e) {
// Validate input data
Log::error('OpenAI validation error:', ['error' => $e->getMessage()]);
}
Create a dedicated service class to encapsulate OpenAI logic:
class AIService {
public function generateSummary(string $content): string {
$response = OpenAI::chat()->create([
'model' => 'gpt-3.5-turbo',
'messages' => [
['role' => 'system', 'content' => 'Summarize the following text.'],
['role' => 'user', 'content' => $content],
],
'max_tokens' => 100,
]);
return $response->choices[0]->message->content;
}
}
use Illuminate\Support\Facades\Cache;
public function getCachedResponse(string $prompt): string {
return Cache::remember("ai_{$prompt}", now()->addHours(1), function() use ($prompt) {
return OpenAI::chat()->create([...])->choices[0]->message->content;
});
}
public function selectModel(string $taskType): string {
return match ($taskType) {
'summary' => 'gpt-3.5-turbo',
'code' => 'code-davinci-002',
'default' => 'gpt-4',
};
}
// Unit test example
public function test_ai_summary_generation() {
OpenAI::fake([
Chat\CreateResponse::fake([
'choices' => [
['message' => ['content' => 'Test summary']],
],
]),
]);
$summary = $this->aiService->generateSummary('Test content');
$this->assertEquals('Test summary', $summary);
OpenAI::assertSent(Chat\Create::class, function ($method, $parameters) {
return $method === 'create' &&
$parameters['messages'][1]['content'] === 'Test content';
});
}
Rate Limits
gpt-3.5-turbo).OpenAI::setRateLimitHandler() to implement custom retry logic or cache responses aggressively.X-RateLimit-* headers in the response.Token Count Mismanagement
OpenAI::tokenizer()->countTokens($text) to validate input length before calling the API.Streaming Quirks
yield or improper loop termination can cause memory leaks.$response = OpenAI::chat()->create([..., 'stream' => true]);
foreach ($response as $chunk) {
if (isset($chunk->choices[0]->delta->content)) {
echo $chunk->choices[0]->delta->content;
}
// Critical: Flush output buffer to avoid buffering issues
if (function_exists('ob_flush')) ob_flush();
flush();
}
Facade vs. Direct Client
OpenAI::chat()) is convenient but less flexible than the underlying client (\OpenAI\Client).$client = app(\OpenAI\Client::class);
$response = $client->chat()->create([...]); // For advanced use cases
Environment-Specific Config
config/openai.php bypasses Laravel’s environment system..env variables. The package respects OPENAI_API_KEY by default.Enable HTTP Logging
Add to config/logging.php:
'channels' => [
'openai' => [
'driver' => 'monolog',
'handler' => \OpenAI\Laravel\Logging\OpenAIHandler::class,
'with' => ['tag' => 'openai'],
],
],
Then use:
OpenAI::setLogger(app('log')->channel('openai'));
Validate API Responses
Use dd() or dump() on the full response object to inspect:
$response = OpenAI::chat()->create([...]);
dd($response->toArray()); // Inspect raw data
Common HTTP Errors
OPENAI_API_KEY and organization.messages array structure).Custom Headers Override default headers in the service provider:
// app/Providers/OpenAIServiceProvider.php
public function register() {
$this->app->singleton(\OpenAI\Client::class, function ($app) {
$client = OpenAI::client([
'headers' => [
'Custom-Header' => 'value',
],
]);
return $client;
});
}
Middleware for Requests Add preprocessing/POST-processing:
OpenAI::setRequestMiddleware(function ($request) {
$request->withHeader('X-Custom-ID', Str::uuid());
});
OpenAI::setResponseMiddleware(function ($response) {
if ($response->statusCode === 200) {
$response->withHeader('X-Processed', 'true');
}
});
Event Listeners
How can I help you explore Laravel packages today?