You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP cURL异步API改造求助:需等待HTTP 200及状态校验

Hey there! Let's walk through refactoring your PHP cURL code to fit that asynchronous API workflow. I’ll break this down into clear, reusable functions with comments so even if you’re new to cURL, you can follow along easily.

1. Asynchronous API Workflow Breakdown

First, let's align on the exact steps we need to implement:

  • Send an initialization request to kick off the async process
  • Wait (or poll) by sending status check requests until the API returns Completed status
    • If status is Processing, retry after a short delay
    • Stop retrying after a set number of attempts to avoid infinite loops
  • Only use the data once the status confirms it’s ready
2. Refactored PHP cURL Code

Here’s a complete, production-ready implementation with error handling and retry logic:

<?php

/**
 * Send initialization request to the async API
 * @param string $initUrl URL for initialization endpoint
 * @param array $initData Data to send with initialization request
 * @return string|null Returns the job ID if successful, null on failure
 */
function sendInitRequest(string $initUrl, array $initData): ?string {
    $ch = curl_init($initUrl);
    
    // Set cURL options
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($initData),
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            // Add any auth headers here, e.g., 'Authorization: Bearer YOUR_TOKEN'
        ],
        CURLOPT_TIMEOUT => 30, // Timeout after 30 seconds
    ]);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    
    curl_close($ch);
    
    // Handle errors
    if ($error) {
        error_log("Initialization cURL error: " . $error);
        return null;
    }
    
    // Check for successful HTTP status (200 OK)
    if ($httpCode !== 200) {
        error_log("Initialization failed with HTTP code: " . $httpCode . ", Response: " . $response);
        return null;
    }
    
    // Parse JSON response
    $responseData = json_decode($response, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        error_log("Failed to parse initialization response: " . json_last_error_msg());
        return null;
    }
    
    // Return the job ID (adjust key based on your API's response)
    return $responseData['job_id'] ?? null;
}

/**
 * Check status of the async job
 * @param string $statusUrl URL for status query endpoint
 * @param string $jobId ID returned from initialization request
 * @return array|null Returns status and data if successful, null on failure
 */
function checkJobStatus(string $statusUrl, string $jobId): ?array {
    // Build query URL with job ID (adjust based on your API's expected format)
    $queryUrl = $statusUrl . "?job_id=" . urlencode($jobId);
    
    $ch = curl_init($queryUrl);
    
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            // Add auth headers here if needed
        ],
        CURLOPT_TIMEOUT => 10, // Shorter timeout for status checks
    ]);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    
    curl_close($ch);
    
    if ($error) {
        error_log("Status check cURL error: " . $error);
        return null;
    }
    
    if ($httpCode !== 200) {
        error_log("Status check failed with HTTP code: " . $httpCode . ", Response: " . $response);
        return null;
    }
    
    $responseData = json_decode($response, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        error_log("Failed to parse status response: " . json_last_error_msg());
        return null;
    }
    
    // Return status and data (adjust keys based on your API)
    return [
        'status' => $responseData['status'] ?? null,
        'data' => $responseData['data'] ?? null
    ];
}

// ------------------------------
// Main Execution Flow
// ------------------------------

// Configuration - adjust these values for your API
$INIT_API_URL = "https://your-api.com/initialize-job";
$STATUS_API_URL = "https://your-api.com/check-job-status";
$MAX_RETRIES = 10; // Max number of status checks
$RETRY_DELAY = 2; // Seconds between retries
$initPayload = [
    // Your initialization data here, e.g., 'input' => 'your-data'
];

// Step 1: Send initialization request
$jobId = sendInitRequest($INIT_API_URL, $initPayload);
if (!$jobId) {
    die("Failed to initialize async job");
}

echo "Job initialized with ID: " . $jobId . "\n";

// Step 2: Poll for job completion
$currentRetry = 0;
$jobCompleted = false;
$finalData = null;

while ($currentRetry < $MAX_RETRIES && !$jobCompleted) {
    // Wait before checking status (skip first delay if API returns immediately)
    if ($currentRetry > 0) {
        sleep($RETRY_DELAY);
    }
    
    $statusResponse = checkJobStatus($STATUS_API_URL, $jobId);
    if (!$statusResponse) {
        $currentRetry++;
        continue;
    }
    
    switch ($statusResponse['status']) {
        case 'Completed':
            $jobCompleted = true;
            $finalData = $statusResponse['data'];
            break;
        case 'Processing':
            echo "Job still processing... Retry " . ($currentRetry + 1) . "/" . $MAX_RETRIES . "\n";
            $currentRetry++;
            break;
        default:
            error_log("Unexpected job status: " . $statusResponse['status']);
            $currentRetry = $MAX_RETRIES; // Exit loop
            break;
    }
}

// Step 3: Process the result
if ($jobCompleted && $finalData) {
    echo "Job completed successfully!\n";
    // Use your data here, e.g., print_r($finalData);
    print_r($finalData);
} else {
    echo "Job timed out or failed after " . $MAX_RETRIES . " retries\n";
}
?>
3. Key Improvements & Important Notes

Let’s go over the critical parts that make this code robust:

  • Modular Functions: Split initialization and status checking into separate functions for reusability and readability
  • Error Handling: Catches cURL errors, invalid HTTP status codes, and JSON parsing failures (logs errors for debugging)
  • Controlled Retries: Uses MAX_RETRIES and RETRY_DELAY to avoid overwhelming the API or getting stuck in an infinite loop
  • Strict Status Validation: Only proceeds when the API explicitly returns Completed; handles unexpected statuses gracefully
  • Configurable Values: All API URLs and retry settings are at the top for easy adjustment
  • URL Encoding: Uses urlencode() for the job ID to avoid issues with special characters in the URL
4. Quick Adjustments for Your API

You’ll need to tweak a few parts to match your specific API:

  • Update $INIT_API_URL and $STATUS_API_URL to your actual endpoints
  • Adjust the auth headers in both functions if your API requires authentication (e.g., Bearer tokens, API keys)
  • Modify the JSON key names (like job_id, status, data) to match what your API returns
  • Adjust $MAX_RETRIES and $RETRY_DELAY based on your API’s expected processing time (10 retries at 2s each = 20s total wait, which matches your original requirement)

内容的提问来源于stack exchange,提问作者gdr39

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:27:13