我使用滚动cUrl PHP库从JSON API中获取数据。
在Rolling CURL库文档中,我尝试了以下示例,效果非常好:
$rollingCurl = new 'RollingCurl'RollingCurl();
$rollingCurl
->get('https://www.google.com')
->get('http://www.msn.com')
->setCallback(function('RollingCurl'Request $request, 'RollingCurl'RollingCurl $rollingCurl) {
// parsing html with regex is evil (http://bit.ly/3x9sQX), but this is just a demo
if (preg_match("#<title>(.*)</title>#i", $request->getResponseText(), $out)) {
$title = $out[1];
}
else {
$title = '[No Title Tag Found]';
}
echo "Fetch complete for (" . $request->getUrl() . ") $title " . PHP_EOL;
})
->setSimultaneousLimit(3)
->execute();
和我试图改变它为我的需要,并保存数据为每个"刮"在一个数组中,但我找不到一种方法来保存数据从回调或它之外。
这是我尝试过的:
$rollingCurl = new 'RollingCurl'RollingCurl();
$rollingCurl
->get('https://www.myapi.com')
->get('https://www.myapi2.com')
->setCallback(function('RollingCurl'Request $request, 'RollingCurl'RollingCurl $rollingCurl) {
$output = json_decode($request->getResponseText());
$data[$x++] = $output; //How do I save it outside this function?
})
->setSimultaneousLimit(3)
->execute();
//Can I get the content of each API call without the callback?
print_r($data); // returns nothing :(
所以我的问题是:
我如何保存数据数组这个函数之外?
我可以得到每个API调用的内容没有回调(执行后)?
我认为在回调闭包中初始化$data
和use
应该可以解决您的问题。如果没有,你的$data
数组只设置在闭包的范围内(声明回调函数时注意use (&$data)
):
/** IMPORTANT **/
$data = array();
/***************/
$rollingCurl = new 'RollingCurl'RollingCurl();
$rollingCurl
->get('https://www.myapi.com')
->get('https://www.myapi2.com')
->setCallback(function('RollingCurl'Request $request, 'RollingCurl'RollingCurl $rollingCurl) use (&$data) {
$output = json_decode($request->getResponseText());
$data[$x++] = $output;
})
->setSimultaneousLimit(3)
->execute();
// Yes, you can!
print_r($data);
我喜欢的另一个很好的特性是Closure作用域绑定,这只是一个快速且未经测试的例子(如果您需要更多的例子,请告诉我:)):
class CurlHandler {
$data = array();
public function processOutput($data) {
// Do something with the data retrieved here
$this->data[] = $data;
}
public function getData() { return $this->data; }
}
$curlResponseHandler = new CurlHandler();
// Your callback to be passed into 'RollingCurl'RollingCurl::setCallback()
$closure = function('RollingCurl'Request $request, 'RollingCurl'RollingCurl $rollingCurl) {
$output = json_decode($request->getResponseText());
$this->processOutput($output);
}
// Bind your callback Closure to your CurlHandler scope
// => the scope binding makes $this inside your callback Closure refer to your CurlHandler instance
$closure->bindTo($curlResponseHandler);
$rollingCurl = new 'RollingCurl'RollingCurl();
$rollingCurl
->get('https://www.myapi.com')
->get('https://www.myapi2.com')
->setCallback($closure)
->setSimultaneousLimit(3)
->execute();
// Get all your outputs from your CurlHandler class now:
print_r($curlResponseHandler->getData());
或者最后但并非最不重要的是直接在你的CurlHandler类上构造一个回调,这可能是我在这种情况下最喜欢的:
class CurlHandler {
$data = array();
public function processOutput('RollingCurl'Request $request, 'RollingCurl'RollingCurl $rollingCurl) {
$output = json_decode($request->getResponseText());
$this->data[] = $output;
}
public function getData() { return $this->data; }
}
$curlResponseHandler = new CurlHandler();
$rollingCurl = new 'RollingCurl'RollingCurl();
$rollingCurl
->get('https://www.myapi.com')
->get('https://www.myapi2.com')
->setCallback(array($curlResponseHandler, 'processOutput'))
->setSimultaneousLimit(3)
->execute();
// Get all your outputs from your CurlHandler class now:
print_r($curlResponseHandler->getData());
最后一个选项假设setCallback()
一般接受可调用对象,而不仅仅是Closure
。
希望有帮助,干杯!