openai-php/client
The standalone PHP client for OpenAI-compatible APIs.Installation
Copy
composer require openai-php/client
Configuration
Copy
<?php
use OpenAI;
$client = OpenAI::factory()
->withApiKey($_ENV['LUMENFALL_API_KEY'])
->withBaseUri('https://api.lumenfall.ai/openai/v1')
->make();
Generate images
Copy
<?php
use OpenAI;
$client = OpenAI::factory()
->withApiKey($_ENV['LUMENFALL_API_KEY'])
->withBaseUri('https://api.lumenfall.ai/openai/v1')
->make();
$response = $client->images()->create([
'model' => 'gemini-3-pro-image',
'prompt' => 'A serene mountain landscape at sunset with dramatic clouds',
'n' => 1,
'size' => '1024x1024',
]);
echo $response->data[0]->url;
Generation options
Copy
$response = $client->images()->create([
'model' => 'gpt-image-1.5',
'prompt' => 'A beautiful garden with roses',
'n' => 1,
'size' => '1792x1024', // landscape
'quality' => 'hd',
'style' => 'natural',
'response_format' => 'url',
]);
Get base64 response
Copy
$response = $client->images()->create([
'model' => 'gpt-image-1.5',
'prompt' => 'A cute robot painting',
'response_format' => 'b64_json',
]);
$base64Image = $response->data[0]->b64_json;
Edit images
Copy
<?php
use OpenAI;
$client = OpenAI::factory()
->withApiKey($_ENV['LUMENFALL_API_KEY'])
->withBaseUri('https://api.lumenfall.ai/openai/v1')
->make();
$response = $client->images()->edit([
'model' => 'gpt-image-1.5',
'image' => fopen('original.png', 'r'),
'prompt' => 'Add a rainbow in the sky',
'n' => 1,
'size' => '1024x1024',
]);
echo $response->data[0]->url;
With a mask
Copy
$response = $client->images()->edit([
'model' => 'gpt-image-1.5',
'image' => fopen('original.png', 'r'),
'mask' => fopen('mask.png', 'r'),
'prompt' => 'A sunlit indoor lounge area with a pool',
'n' => 1,
'size' => '1024x1024',
]);
List models
Copy
$response = $client->models()->list();
foreach ($response->data as $model) {
echo $model->id . PHP_EOL;
}
Error handling
Copy
<?php
use OpenAI;
use OpenAI\Exceptions\ErrorException;
use OpenAI\Exceptions\TransporterException;
$client = OpenAI::factory()
->withApiKey($_ENV['LUMENFALL_API_KEY'])
->withBaseUri('https://api.lumenfall.ai/openai/v1')
->make();
try {
$response = $client->images()->create([
'model' => 'gemini-3-pro-image',
'prompt' => 'A beautiful sunset',
]);
echo $response->data[0]->url;
} catch (ErrorException $e) {
$error = $e->getErrorMessage();
$code = $e->getErrorCode();
if ($code === 'AUTHENTICATION_FAILED') {
echo 'Invalid API key';
} elseif ($code === 'RATE_LIMITED') {
echo 'Rate limit exceeded';
} elseif ($code === 'INSUFFICIENT_BALANCE') {
echo 'Insufficient balance';
} else {
echo "API Error: $error";
}
} catch (TransporterException $e) {
echo 'Network error: ' . $e->getMessage();
}
openai-php/laravel
The Laravel integration for openai-php.Installation
Copy
composer require openai-php/laravel
Copy
php artisan vendor:publish --provider="OpenAI\Laravel\ServiceProvider"
Configuration
Updateconfig/openai.php:
Copy
<?php
return [
'api_key' => env('LUMENFALL_API_KEY'),
'base_uri' => 'https://api.lumenfall.ai/openai/v1',
'organization' => null,
'request_timeout' => 30,
];
.env:
Copy
LUMENFALL_API_KEY=lmnfl_your_api_key
OPENAI_BASE_URI=https://api.lumenfall.ai/openai/v1
Generate images
Using the Facade:Copy
<?php
namespace App\Http\Controllers;
use OpenAI\Laravel\Facades\OpenAI;
class ImageController extends Controller
{
public function generate()
{
$response = OpenAI::images()->create([
'model' => 'gemini-3-pro-image',
'prompt' => 'A serene mountain landscape at sunset with dramatic clouds',
'n' => 1,
'size' => '1024x1024',
]);
return response()->json([
'url' => $response->data[0]->url
]);
}
}
Using dependency injection
Copy
<?php
namespace App\Services;
use OpenAI\Client;
class ImageGenerationService
{
public function __construct(
private Client $client
) {}
public function generate(string $prompt, string $model = 'gemini-3-pro-image'): string
{
$response = $this->client->images()->create([
'model' => $model,
'prompt' => $prompt,
'n' => 1,
'size' => '1024x1024',
]);
return $response->data[0]->url;
}
}
Edit images
Copy
<?php
namespace App\Http\Controllers;
use OpenAI\Laravel\Facades\OpenAI;
use Illuminate\Http\Request;
class ImageEditController extends Controller
{
public function edit(Request $request)
{
$request->validate([
'image' => 'required|image',
'prompt' => 'required|string',
]);
$response = OpenAI::images()->edit([
'model' => 'gpt-image-1.5',
'image' => fopen($request->file('image')->path(), 'r'),
'prompt' => $request->input('prompt'),
'n' => 1,
'size' => '1024x1024',
]);
return response()->json([
'url' => $response->data[0]->url
]);
}
}
Queued job example
Copy
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use OpenAI\Laravel\Facades\OpenAI;
use App\Models\GeneratedImage;
class GenerateImageJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(
public string $prompt,
public string $model,
public int $userId
) {}
public function handle(): void
{
$response = OpenAI::images()->create([
'model' => $this->model,
'prompt' => $this->prompt,
'n' => 1,
'size' => '1024x1024',
]);
GeneratedImage::create([
'user_id' => $this->userId,
'prompt' => $this->prompt,
'model' => $this->model,
'url' => $response->data[0]->url,
]);
}
}
// Dispatch the job
GenerateImageJob::dispatch(
prompt: 'A beautiful landscape',
model: 'gemini-3-pro-image',
userId: auth()->id()
);
Error handling in Laravel
Copy
<?php
namespace App\Http\Controllers;
use OpenAI\Laravel\Facades\OpenAI;
use OpenAI\Exceptions\ErrorException;
use Illuminate\Http\Request;
class ImageController extends Controller
{
public function generate(Request $request)
{
try {
$response = OpenAI::images()->create([
'model' => 'gemini-3-pro-image',
'prompt' => $request->input('prompt'),
]);
return response()->json([
'url' => $response->data[0]->url
]);
} catch (ErrorException $e) {
$code = $e->getErrorCode();
return match ($code) {
'AUTHENTICATION_FAILED' => response()->json([
'error' => 'Invalid API key'
], 401),
'RATE_LIMITED' => response()->json([
'error' => 'Rate limit exceeded'
], 429),
'INSUFFICIENT_BALANCE' => response()->json([
'error' => 'Insufficient balance'
], 402),
default => response()->json([
'error' => $e->getErrorMessage()
], 500),
};
}
}
}