慎用file_get_contents函数

慎用file_get_contents函数

15 Jan 2019

PHPer都知道有一个file_get_contents函数,在一些简单的网络请求场景下非常方便,直接调用求情url即可。最近做项目出现了一个怪事,访问站点经常莫名其妙出现卡死、访问超时,排查了很久最后定位到问题点,原来有个地方需要抓取微信头像,使用了file_get_contents函数,网络请求的时候出现卡死,google了一下最终找到了病根。

 

file_get_contents函数顾名思义,其本质是实现资源读取,因为其使用方便,在很多网络请求的场景下经常拿来做http请求。但是有一个问题,这个函数默认情况下会一直请求资源,直到获取到结果为止。这就很容易造成大量的进程阻塞,最终直接卡死。知道了病根就好办了,有两种解决办法:

1)给定一个超时的时间

$opts = array(
  'http'=>array(
    'method'=>"GET",
    'timeout'=>10,
  )
);
$context = stream_context_create($opts);
$result =file_get_contents('http://www.xxx.com', false, $context);

2)使用curl替代(推荐),以下是我经常用到的一个curl封装函数

/**
 * curl请求
 * @param $url 请求url
 * @param $params 请求参数
 * @param string $method 请求方式
 * @param array $header 请求头部
 * @param bool $multi 是否文件上传
 * @return bool|mixed
 */
function sendCurl($url, $params, $method = 'GET', $header = array(), $multi = false)
{
    $opts = array(
        CURLOPT_TIMEOUT => 30,
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_HTTPHEADER => $header
    );


    switch (strtoupper($method)) {
        case 'GET':
            $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
            break;
        case 'POST':
            $params = $multi ? $params : http_build_query($params);
            $opts[CURLOPT_URL] = $url;
            $opts[CURLOPT_POST] = 1;
            $opts[CURLOPT_POSTFIELDS] = $params;
            break;
        default:
            return false;
    }

    $ch = curl_init();
    curl_setopt_array($ch, $opts);
    $data = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    if ($error) return false;
    return $data;
}