最早在 SmarterUS 改版的时候,后台数据采用了 API 的方式来提供,当时我第一次想要获取 API 数据时,天真的使用了 file_get_contents
函数,结果在自己的机器上能正常获取 XML 数据,但是代码一上到公司的开发机,获取 API 时返回竟然是空白页面,实在是百思不得其解。
既然 file_get_contents
不能起作用,那就换个方式,用 curl
来获取远程数据好了。当然用 curl
能成功地获取数据,但是我还是有疑问——为什么 file_get_contents
就是不行呢?
当时没多想是什么原因,后来回家来查了一下, file_get_contents
有个参数设置叫 allow_url_fopen
,如果设置为 off
的话,那么这个函数就不能获取远程 url 的内容,所以换成 curl
来获取远程内容才是正确的做法。但是原因不止这一个,还有更重要的原因应该选择 curl
,这就是这两者的效率问题。
写段测试代码来看看到底这两者的效率到底有何差异:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| <?php
error_reporting(E_ALL);
ini_set('display_errors', 'on');
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();
class Remote {
const FILE_GET_CONTENTS = 1;
const CURL = 2;
protected $_startTime;
protected $_endTime;
public static function getMicroTime() {
return microtime(true);
}
public static function getContentByFileGetContents($url) {
$result = file_get_contents($url);
return $result;
}
public static function getContentByCurl($url) {
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
public function remoteOpen($url, $type, $loop=10) {
switch ($type) {
case self::FILE_GET_CONTENTS:
$method = 'getContentByFileGetContents';
break;
case self::CURL:
$method = 'getContentByCurl';
break;
default:
throw new Exception('No such type!');
break;
}
$this->_startTime = self::getMicroTime();
for ($i=0; $i<$loop; $i++) {
// Zend_Debug::dump('calling method ' . __CLASS__ . '::' . $method . '.');
$result = self::{$method}($url);
// Zend_Debug::dump($result);
}
$this->_endTime = self::getMicroTime();
Zend_Debug::dump($this->_endTime - $this->_startTime);
}
}
$r = new Remote();
$url = 'http://ip.taobao.com/service/getIpInfo.php?ip=210.210.200.200';
$r->remoteOpen($url, Remote::FILE_GET_CONTENTS);
$r->remoteOpen($url, Remote::CURL);
|
运行后看看输出结果:
1
2
3
4
5
| > php curl.php
double(2.9429008960724)
double(2.1207449436188)
|
不过在多次运行这条程序的情况下,偶尔会出现用 curl
比 file_get_contents
要消耗更长的时间。不过由于 curl
有更强的定制性,因此还是推荐使用 curl
。
Google 了一下 curl
和 file_get_contents
的区别,主要有下面这几个点:
1、file_get_contents
不会缓存 DNS ,但是 curl
会。
2、file_get_contents
不能 keepalive ,但是 curl
可以。
如此一来,在读取本地文件的场景下,应该使用 file_get_contents
;而在获取远程数据时,应该使用 curl
。
Have a nice day!