本文目录导读:

我来详细说明PHP项目对接AI绘图后端接口的完整流程:
主流AI绘图API提供商
| 服务商 | 接口类型 | 特点 |
|---|---|---|
| Stable Diffusion | 自建/API | 开源可控,可本地部署 |
| DALL-E 3 | OpenAI API | 质量高,费用较高 |
| Midjourney | Discord API | 艺术风格好,需额外封装 |
| 百度文心一格 | REST API | 国内访问快 |
PHP后端对接示例(以Stable Diffusion为例)
1 发送绘图请求
<?php
class AIImageGenerator {
private $apiUrl;
private $apiKey;
public function __construct($apiUrl, $apiKey = '') {
$this->apiUrl = $apiUrl;
$this->apiKey = $apiKey;
}
/**
* 生成图像
* @param string $prompt 描述文本
* @param array $options 附加参数
* @return array 返回结果
*/
public function generate($prompt, $options = []) {
$payload = array_merge([
'prompt' => $prompt,
'negative_prompt' => '',
'width' => 512,
'height' => 512,
'steps' => 20,
'cfg_scale' => 7,
'batch_size' => 1
], $options);
$ch = curl_init($this->apiUrl . '/sdapi/v1/txt2img');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->apiKey
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120, // 生成可能需要较长时间
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("API请求失败: HTTP {$httpCode}");
}
return json_decode($response, true);
}
}
// 使用示例
$generator = new AIImageGenerator('http://localhost:7860');
try {
$result = $generator->generate('一只可爱的柴犬在草地上奔跑', [
'width' => 1024,
'height' => 1024,
'steps' => 30
]);
// 处理返回的base64图像数据
$imageData = $result['images'][0];
file_put_contents('generated_image.png', base64_decode($imageData));
echo "图像生成成功!";
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
2 使用OpenAI DALL-E 3
<?php
class DallEAPI {
private $apiKey;
public function __construct($apiKey) {
$this->apiKey = $apiKey;
}
public function generateImage($prompt, $size = '1024x1024', $quality = 'standard') {
$data = [
'model' => 'dall-e-3',
'prompt' => $prompt,
'n' => 1,
'size' => $size,
'quality' => $quality
];
$ch = curl_init('https://api.openai.com/v1/images/generations');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->apiKey
],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
$error = json_decode($response, true);
throw new Exception("API错误: " . ($error['error']['message'] ?? '未知错误'));
}
return json_decode($response, true);
}
}
// 使用示例
$dalle = new DallEAPI('sk-your-api-key-here');
$result = $dalle->generateImage('Sunset over mountains, digital art style');
$imageUrl = $result['data'][0]['url'];
// 下载保存图像
$imageContent = file_get_contents($imageUrl);
file_put_contents('dalle_image.png', $imageContent);
异步任务处理(推荐方案)
<?php
// 异步绘图任务类
class AsyncImageGenerator {
private $db;
private $apiClient;
public function __construct($db, $apiClient) {
$this->db = $db;
$this->apiClient = $apiClient;
}
/**
* 创建绘图任务
*/
public function createTask($prompt, $userId, $options = []) {
$taskId = uniqid('img_', true);
// 保存任务到数据库
$stmt = $this->db->prepare("INSERT INTO image_tasks (task_id, user_id, prompt, options, status, created_at)
VALUES (?, ?, ?, ?, 'pending', NOW())");
$stmt->execute([
$taskId,
$userId,
$prompt,
json_encode($options)
]);
// 将任务加入队列(使用Redis或消息队列)
$this->addToQueue($taskId, [
'prompt' => $prompt,
'options' => $options
]);
return $taskId;
}
/**
* 检查任务状态
*/
public function checkTask($taskId) {
$stmt = $this->db->prepare("SELECT * FROM image_tasks WHERE task_id = ?");
$stmt->execute([$taskId]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
/**
* 处理队列中的任务(由Worker进程调用)
*/
public function processQueue() {
$task = $this->getNextTaskFromQueue();
if (!$task) return;
try {
// 更新状态为处理中
$this->updateTaskStatus($task['id'], 'processing');
// 调用API生成图像
$result = $this->apiClient->generate(
$task['prompt'],
json_decode($task['options'], true)
);
// 保存图像到服务器
$imagePath = $this->saveImage($result);
// 更新任务状态为完成
$this->updateTaskStatus($task['id'], 'completed', $imagePath);
} catch (Exception $e) {
// 标记为失败
$this->updateTaskStatus($task['id'], 'failed', null, $e->getMessage());
}
}
private function saveImage($result) {
// 处理并保存图像
$filename = uniqid() . '.png';
$path = '/uploads/images/' . $filename;
if (isset($result['images'][0])) {
// base64格式
file_put_contents($_SERVER['DOCUMENT_ROOT'] . $path,
base64_decode($result['images'][0]));
} elseif (isset($result['data'][0]['url'])) {
// URL格式
file_put_contents($_SERVER['DOCUMENT_ROOT'] . $path,
file_get_contents($result['data'][0]['url']));
}
return $path;
}
}
前端请求示例
// 前端JavaScript请求示例
async function generateImage() {
const prompt = document.getElementById('prompt').value;
const response = await fetch('/api/generate-image', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': 'your-csrf-token'
},
body: JSON.stringify({ prompt: prompt })
});
const result = await response.json();
if (result.success) {
// 轮询任务状态
pollTaskStatus(result.task_id);
}
}
// 轮询任务状态
async function pollTaskStatus(taskId) {
const interval = setInterval(async () => {
const response = await fetch(`/api/task-status/${taskId}`);
const status = await response.json();
if (status.status === 'completed') {
clearInterval(interval);
// 显示生成的图像
displayImage(status.image_url);
} else if (status.status === 'failed') {
clearInterval(interval);
showError(status.error_message);
}
}, 2000);
}
关键注意事项
1 错误处理
// 统一的错误处理中间件
class ImageAPIException extends Exception {
public function __construct($message, $code = 400) {
parent::__construct($message, $code);
}
}
// 请求验证
function validatePrompt($prompt) {
// 过滤敏感词
$blockedWords = ['暴力', '色情', '敏感内容'];
foreach ($blockedWords as $word) {
if (strpos($prompt, $word) !== false) {
throw new ImageAPIException('包含不允许的内容');
}
}
// 长度限制
if (strlen($prompt) > 1000) {
throw new ImageAPIException('描述文本过长');
}
}
2 性能优化
// 图像缓存
class ImageCache {
private $cacheDir = '/tmp/image-cache/';
public function getCached($prompt, $options) {
$hash = md5($prompt . json_encode($options));
$cacheFile = $this->cacheDir . $hash . '.png';
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 86400)) {
return $cacheFile;
}
return null;
}
public function setCache($prompt, $options, $imageData) {
$hash = md5($prompt . json_encode($options));
file_put_contents($this->cacheDir . $hash . '.png', $imageData);
}
}
完整API接口示例
// router.php
Route::post('/api/generate-image', function() {
$input = json_decode(file_get_contents('php://input'), true);
try {
// 验证输入
validatePrompt($input['prompt']);
// 检查用户配额
$quota = checkUserQuota($_SESSION['user_id']);
if ($quota <= 0) {
throw new ImageAPIException('今日生成次数已用完');
}
// 创建任务
$generator = new AsyncImageGenerator($db, $apiClient);
$taskId = $generator->createTask(
$input['prompt'],
$_SESSION['user_id'],
$input['options'] ?? []
);
// 扣减配额
deductQuota($_SESSION['user_id']);
return json_encode([
'success' => true,
'task_id' => $taskId,
'message' => '任务已创建'
]);
} catch (Exception $e) {
http_response_code($e->getCode() ?: 400);
return json_encode([
'success' => false,
'error' => $e->getMessage()
]);
}
});
部署建议
- 本地部署Stable Diffusion:使用Automatic1111 WebUI API
- 生产环境:使用消息队列(Redis/RabbitMQ)处理异步任务
- 图像存储:建议使用云存储服务(OSS/S3)
- 费用控制:实现用户配额和速率限制
- 监控告警:记录API调用次数、成功率和响应时间
这样可以构建一个稳定、可扩展的AI绘图系统。