Параллельный запрос cURL с обратным вызовом WRITEFUNCTION

Я пытаюсь ограничить свои ответы cURL, как предлагается в этих сообщениях: Получить частичную веб-страницу, и PHP CURLOPT_WRITEFUNCTION, похоже, не работает. Идея состоит в том, чтобы ограничить ответ 4000 символами, как указано в функции обратного вызова.

Я написал следующую функцию, но я уже знаю, что это не имеет смысла, потому что параметр в определении функции обратного вызова не изменяется внутри цикла, как это было бы в вызове функции. К моменту фактического вызова функций значение $key будет фиксированным, поэтому мои ссылки на этот индекс не изменятся.

Кажется, мне нужна новая функция замыкания для каждого из циклов, и каждый из них должен ссылаться на свою собственную переменную $full_length. Однако я не понимаю, как это возможно. Для того, чтобы сделать это, кажется, мне нужно как-то сделать ссылку на объект замыкания, чтобы указать конкретную переменную $full_length.

Любая помощь будет оценена. Благодарю.

function get_headers($urls){
    $curly = array();
    $result = array();
    $mh = curl_multi_init();
    $obj = $this;
    foreach ($urls as $key => $url) {
        $this->full_length[$key] = 0;
        $callback = function ($ch, $string) use ($obj, $key){
                    $length = strlen($string);
                    $obj->full_length[$key] += $length;
                    if($obj->full_length[$key] >= 4000){
                        return -1;
                    }
                    return $length;
                };
        $curly[$key] = curl_init
        curl_setopt($curly[$key], CURLOPT_URL,            $url);
        curl_setopt($curly[$key], CURLOPT_HEADER,         0);
        curl_setopt($curly[$key], CURLOPT_WRITEFUNCTION, $callback);
        curl_setopt($curly[$key], CURLOPT_RETURNTRANSFER, 1);
        curl_multi_add_handle($mh, $curly[$key]);
    }
    $running = null;
    do {
        curl_multi_exec($mh, $running);
    } while($running > 0);
    foreach($curly as $key => $cnt) {
        $content = curl_multi_getcontent($cnt);
        curl_multi_remove_handle($mh, $cnt);
        if (strlen($content) > 0){
            $result[$key] = $content;
        } else {
            curl_multi_close($mh);
            return FALSE;
        }
    }
    curl_multi_close($mh);
    return $result;
}

РЕДАКТИРОВАТЬ:

Я нашел сообщение, которое делает именно то, что я пытаюсь сделать, но оно в javascript: закрытие внутри цикла for - обратный вызов с переменной цикла в качестве параметра. Я написал следующую функцию, чтобы попытаться сделать то же самое в PHP:

function get_write_function($key){
    $this->full_length[$key] = 0;
    $obj = $this;
    $funky = function ($ch, $str) use ($obj, $key){
        $length = strlen($str);
        $obj->full_length[$key] += $length;
        if($obj->full_length[$key] >= 4000){
            return -1;
        }
        return $length;
    };
    return $funky;
}

Код работал без ошибок, но он все еще не делал то, что я хотел. После закрытия моих дескрипторов cURL я сбросил массив $full_length, и он только показал:

array([0] => 0, [1] => 0)

Это указывает на то, что они были инициализированы функцией get_write_function (поскольку я ничего не инициализировал в объявлении класса), но впоследствии значения никогда не обновлялись.

1 ответ

Решение

Я наконец понял это. Самая большая проблема заключалась в том, что cURL игнорировал WRITEFUNCTION, пока я не разместил его в качестве самого последнего указанного параметра, как я написал здесь: cURL WRITEFUNCTION not Called. Я фактически не нуждался в обратном переносе, так как я записал вывод в переменную класса. Это было необходимо, потому что, когда обратный вызов возвращает -1, ничего не возвращается. Следующий код прекрасно работает:

var $full_length = array();
var $result = array();

function get_headers($urls){
    $curly = array();
    $mh = curl_multi_init();
    foreach ($urls as $key => $url) {
        $callback = $this->get_write_function($key);
        $curly[$key] = curl_init
        curl_setopt($curly[$key], CURLOPT_URL,            $url);
        curl_setopt($curly[$key], CURLOPT_HEADER,         0);
        curl_setopt($curly[$key], CURLOPT_WRITEFUNCTION, $callback);
        curl_multi_add_handle($mh, $curly[$key]);
    }
    $running = null;
    do {
        curl_multi_exec($mh, $running);
    } while($running > 0);
    foreach($curly as $key => $cnt) {
        curl_multi_remove_handle($mh, $cnt);
    }
    curl_multi_close($mh);
    return $this->result;
}

function get_write_function($key){
    $this->full_length[$key] = 0;
    $this->result[$key] = '';
    $obj = $this;
    $funky = function ($ch, $str) use ($obj, $key){
        $obj->result[$key] .= $str;
        $length = strlen($str);
        $obj->full_length[$key] += $length;
        if($obj->full_length[$key] >= 4000){
            return -1;
        }
        return $length;
    };
    return $funky;
}
Другие вопросы по тегам