Рендеринг веб-страницы в PHP без ожидания отклика GET-запросов - PullRequest
0 голосов
/ 08 февраля 2020

У меня есть сайт социальной сети, использующий инфраструктуру Elgg, и я должен сделать повторный вызов внешнего API для каждого поста в блоге, который указан на моей странице активности.

Моя страница зависит от ответа, чтобы определить, какой тип значка отображать в меню для каждого сообщения в блоге. Когда в блоге большое количество постов, страница отрисовывается вечно, так как она ожидает завершения всех ответов перед отображением.

Есть ли способ для PHP немедленно отобразить страницу и затем выполнить вызовы конечной точке в фоновом режиме, а затем обновить значки для каждого сообщения в блоге по мере возврата ответов? Приведенный ниже код должен пролить некоторый свет на то, что я пытаюсь сделать:

// Each blog entity has a menu that is attached, this function is called as we iterate through a collection of blog posts

function river_menu_handler($hook, $type, $items, $params) {
    // Setup environment vars
    $docroot = $_SERVER["DOCUMENT_ROOT"];
    $Dotenv = new Loader($docroot . 'mod/fc-plugin/views/default/resources/.env');
    $Dotenv->parse()->putenv(true);
    $signature_verified = false;
    $address = '';
    $secret = getenv('APP_SECRET');
    $app_id = getenv('APP_ID');
    if (elgg_in_context('widgets')) {
        return $items;
    }
    $item = $params['item'];
    $entity = $item->getObjectEntity();
    if (elgg_instanceof($entity, 'object', 'blog')){
        // call out to api to validate blog post
        $authString = $app_id . ':' . $secret;
        $auth_id = urlencode($entity->auth_id);
        $content_hash = urlencode($entity->content_hash);
        $envelope_id = urlencode($entity->envelope_id);
        $response = validateSignature($auth_id, $content_hash, $envelope_id, $authString);
        $response_json = json_decode($response, true);
        if (isset($response_json['errorCode'])) {
                $errorCode = $response_json['errorCode'];
                if ($errorCode == 0) {
                    $signature_verified = $response_json['signatureVerified'];
                    $address = $response_json['address'];
                    if ($signature_verified) {
                        $items[] = \ElggMenuItem::factory([
                            'name' => 'verify',
                            'href' => 'https://ropsten.etherscan.io/address/' . $address,
                            'text' => elgg_view_icon('round-checkmark'),
                            'title' => 'This post has been Verified',
                            'priority' => 200,
                        ]);
                        return $items;
                    } else {
                        $items[] = \ElggMenuItem::factory([
                            'name' => 'verify',
                            //'href' => 'action/verify_post',
                            'text' => elgg_view_icon('ban'),
                            'title' => 'This post is not Verified',
                            'priority' => 200,
                        ]);
                        return $items;
                    }
                } elseif ($errorCode == 1) {
                    $items[] = \ElggMenuItem::factory([
                        'name' => 'verify',
                        'text' => elgg_view_icon('clock'), 
                        'title' => 'This post is pending Verification',
                        'priority' => 200,
                    ]);
                    return $items;
                } else {
                        $items[] = \ElggMenuItem::factory([
                            'name' => 'verify',
                            'text' => elgg_view_icon('ban'),
                            'title' => 'This post is not Verified',
                            'priority' => 200,
                        ]);
                        return $items;
                    }
            } else {
                // no error code returned here from FactChain but got an exception
                $items[] = \ElggMenuItem::factory([
                    'name' => 'verify',
                    //'href' => 'action/verify_post',
                    'text' => elgg_view_icon('ban'),
                    'title' => 'This post is not Verified',
                    'priority' => 200,
                ]);
                return $items;
            }
    }
    else {
        return;
    }

И служба выполняет запрос cUrl:

function validateSignature($auth_id, $content_hash, $envelope_id, $authString) {
    $ch = curl_init();
    $authorization = 'Authorization: Basic ' . base64_encode($authString);
    $validate_url = 'https://api.myfcapi.com/api/envelopes/validate/' . $auth_id .'/' . $content_hash . '/' . $envelope_id;
    curl_setopt($ch, CURLOPT_URL, $validate_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array($authorization ));
    curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
    $response = curl_exec($ch);
    $json = json_decode($response, true);
    $err = curl_error($ch);
    if($err) {
        echo "cURL Error: " . $err;
    }
    // Check HTTP status code
    if (!curl_errno($ch)) {
        switch ($http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE)) {
            case 200:  # OK
                break;
            case 502:  # server error
                system_message('Received 500 Error from Server');
                break;
            case 400:  # bad request
                $jsonResponse = json_decode($response, true);
                $message = $jsonResponse['message'];
                break;
            default:
                echo 'Unexpected HTTP code: ', $validate_url, "\n";
        }
    }
    curl_close($ch);
    return $response;
}
...