简体   繁体   English

具有WRITEFUNCTION回调的并行cURL请求

[英]Parallel cURL Request with WRITEFUNCTION Callback

I'm trying to limit my cURL responses as suggested in these posts: Retrieve partial web page and PHP CURLOPT_WRITEFUNCTION doesn't appear to be working . 我试图按照这些帖子中的建议限制我的cURL响应: 检索部分网页PHP CURLOPT_WRITEFUNCTION似乎不起作用 The idea is to limit the response to 4000 characters as specified in the callback function. 想法是将响应限制为回调函数中指定的4000个字符。

I wrote the following function, but I already know that it doesn't make sense, because a parameter in the callback function definition doesn't vary within a loop as it would within a function call. 我编写了以下函数,但我已经知道它没有意义,因为回调函数定义中的参数在循环内不会像在函数调用中那样变化。 By the time the functions are actually called, the value for $key is fixed, so my references to that index won't vary. 在实际调用函数时,$ key的值是固定的,因此我对该索引的引用不会改变。

It seems that I need a new closure function for each of the loops, and each one needs to reference its own $full_length variable. 似乎每个循环都需要一个新的关闭函数,每个循环都需要引用自己的$ full_length变量。 However, I don't see how that's possible. 但是,我不知道这怎么可能。 In order to do that, it seems I would have to somehow make a reference the closure object in order to specify the specific $full_length variable. 为了做到这一点,似乎我必须以某种方式引用闭包对象,以指定特定的$ full_length变量。

Any help would be appreciated. 任何帮助,将不胜感激。 Thanks. 谢谢。

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;
}

EDIT: 编辑:

I found a post that does exactly what I'm trying to do, but it's in javascript: closure inside a for loop - callback with loop variable as parameter . 我发现了一篇与我想做的事情完全相同的文章,但是它在javascript中: for循环内的闭包-以loop变量作为parameter的回调 I wrote the following function to try to do the same thing in PHP: 我编写了以下函数来尝试在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;
}

The code ran without errors, but it still didn't do what I wanted. 该代码运行没有错误,但仍然没有实现我想要的功能。 After closing my cURL handles I dumped the $full_length array, and it only showed: 关闭我的cURL句柄后,我转储了$ full_length数组,它仅显示:

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

That indicates that they were initialized by the get_write_function (since I didn't initialize anything in the class declaration), but that the values were never updated afterwards. 这表明它们是由get_write_function初始化的(因为我没有在类声明中初始化任何东西),但是之后从未更新这些值。

I finally got it figured out. 我终于明白了。 The biggest problem was the fact that cURL was ignoring the WRITEFUNCTION until I placed it as the very last option specified, as I posted here: cURL WRITEFUNCTION not Being Called . 最大的问题是cURL一直忽略WRITEFUNCTION,直到我将其放置为指定的最后一个选项为止,正如我在此处发布的内容: cURL WRITEFUNCTION not被调用 I actually didn't need the return transfer, since I wrote the output to a class variable. 实际上,我不需要返回转移,因为我将输出写入了一个类变量。 That was necessary because when the callback returns -1, nothing gets returned. 这是必要的,因为当回调返回-1时,什么也不会返回。 The following code works great: 以下代码效果很好:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM