在PHP后端的开发过程中,除了获取数据库数据和处理数据的内部逻辑外,还经常需要向其他服务器接口请求数据。我们获取数据的方式一般有3种,分别是:file_get_contentsfsockopencurl3种常用接口获取方式简述file_get_contents函数声明:/**函数功能:将整个文件读入一个字符串@param$filename读取文件名或者url,如果是一个文件路径,$use_include_path需要设置为true@param$use_include_path是否使用文件目录路径搜索,如果是文件搜索需要设置为true,默认为false@param$context资源参数,使用stream_context_create创建的context,用于配置读取文件的参数,比如配置HTTP请求的方法和头信息@param$offset开始读取数据的偏移值@param$maxlen从多长时间获取数据$offset@returnstring如果字符串返回成功则为false*/stringfile_get_contents(string$filename,bool$use_include_path=false,resource$context,int$offset=-1,int$maxlen)Instancefetchingdata://作者开发使用Yii2,所以路由控制器使用action的写法publicfunctionactionFetch(){//url是作者另一篇文章写的。测试使用$data=file_get_contents('https://segmentfault.com/a/1190000011549088');//获取到的数据需要先输出,才能在前端请求中看到返回的数据Resultecho$data;//结束请求return$data;}fsockopen函数声明:/**功能:打开一个网络连接或一个Unixsocketconnection@param$hostname初始化socket连接的主机@param$port端口号,不传则端口不适用@param$errno@param$errstr字符串形式的错误信息@param$timeout超时时间,单位s@returnresource如果成功返回文件句柄,可以使用file函数读取Write,returnfalse*/resourcefsockopen(string$hostname,int$port=-1,int&$errno,string&$errstr,float$timeout=ini_get("default_socket_timeout"))instancegetdata:注意:在我的测试环境中报错:`Unabletofindthesockettransport"http"-didyouforgettoenableitwhenyouconfigurePHP?`,是由于php.ini配置问题,所以这种方式不推荐获取,因为受配置文件影响,容易不可用//作者开发使用Yii2,所以路由控制器使用action的写法$fp=fsockopen('https://segmentfault.com/a/1190000011549088',80);if(!$fp){echo"$errstr($errno)
\n";}else{$out="GET/HTTP/1.1\r\n";$out.="主机:www.example.com\r\n";$out.="连接:关闭\r\n\r\n";fwrite($fp,$out);while(!feof($fp)){echofgets($fp,128);}fclose($fp);}cURL需要安装libcurl包。cURL的全称是commandLineUniformResourceLocator,命令行统一资源定位器,用于在命令行上传下载url文件。提供程序开发所需的libcurl包。获取数据的示例://初始化一个curl资源$ch=curl_init('https://segmentfault.com/a/1190000011549088');//执行curl对象并返回结果$data=curl_exec($ch);//关闭cURL资源,释放系统资源curl_close($ch);三种方式的优缺点对比从代码风格上来说,file_get_contents最简洁,fsockopen和curl则比较复杂。关于配置头信息:file_get_contents通过stream_context_set_option()配置头信息;fsockopen可以通过fwirte($socket,$config)或者字符串拼接配置请求头信息,支持异步请求;curl可以通过curl_setopt($curl,$name,$key)来配置请求配置,作为一个lib库,功能强大。PHP不支持多进程,如果需要异步请求,非阻塞方式,请选择fsockopen。对于常规请求,我们使用file_get_contents和curl。除了函数,下面做个性能测试:$url='https://segmentfault.com/a/1190000011549088';//100次file_get_contents请求,结果是113s$start=time();for($i=0;$i<100;$i++){$data=file_get_contents($url);}$end=time();$cost=$end-$start;echo'file_get_contents100timesTotaltimespent:',"$cost";//100次curl请求,结果为48s$start=time();for($i=0;$i<100;$i++){$ch=curl_init($url);//设置不直接输出结果,而是保存在$data中curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);$data=curl_exec($ch);}$end=time();$cost=$end-$start;echo'curl100总耗时:',"$cost";因此,在常规的PHP请求中,我们使用curl来请求接口数据。cURL详解使用curl的基本方法是:curl_init()初始化一个cURL会话curl_setopt()或curl_setopt_array()设置配置选项curl_exec()执行一个会话curl_close()关闭一个会话@param$url请求配置中的url,如果没有通过,需要在curl_setopt()中设置CURLOPT_URL@returnresource如果成功返回cURL句柄,失败则返回false*/resourcecurl_init([string$url=NULL])curl_setopt()和curl_setopt_array()函数声明:/**功能:设置cURL传输选项@param$chcurl_init()返回的cURL句柄@param$optionCURLOPT_XXXoptiontobeset@param$valueoptionoption上设置的值@returnbool成功返回true,失败返回false*/boolcurl_setopt(resource$ch,int$option,mixed$value)/**功能:设置cURL传输选项@param$chcurl_init()@param$options返回的cURL句柄需要CURLOPT_XXX选项和值的数组设置@returnbool全部成功返回true,一个失败立即返回false($ch,CURLOPT_URL,'https://segmentfault.com/a/1190000011549088');curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);//批量设置curl_setopt_array($ch,array(CURLOPT_URL=>'https://段tfault.com/a/1190000011549088',CURLOPT_RETURNTRANSFER=>true));CURLOPT_parameters列出了一些常用的参数,所有参数可以在PHPcurl参数文档中找到CURLOPT_HEADER启用时,头文件的信息将作为数据流输出。当CURLOPT_POST为TRUE时,会发送一个POST请求,类型为:application/x-www-form-urlencoded,这是提交HTML表单时最常见的类型。CURLOPT_RETURNTRANSFERTRUE将curl_exec()获得的信息作为字符串返回,而不是直接输出。CURLOPT_UPLOADTRUE准备上传。CURLOPT_CONNECTTIMEOUT尝试连接时等待的秒数。设置为0无限期等待。CURLOPT_PORT用于指定连接端口。CURLOPT_TIMEOUT允许执行cURL函数的最大秒数。CURLOPT_COOKIE设置HTTP请求的“Cookie:”部分的内容。多个cookie由分号和空格分隔(例如,“fruit=apple;colour=red”)。CURLOPT_POSTFIELDS使用HTTP协议中的“POST”操作发送所有数据。该参数只支持一维数组。如果需要传递多维数组,需要使用http_build_query来处理。更详细的信息可以参考CURLOPT_POSTFIELDS在PHPcURL请求中只支持一维数组一文。CURLOPT_URL需要获取的URL地址,也可以在curl_init()初始化session的时候使用。curl_exec()函数声明:/**函数功能:执行curl会话@param$chcurl_init()返回cURL句柄@returnmixed成功返回true,失败返回false;ifsetCURLOPT_RETRUNTRANSFERtotrue,成功则返回执行结果*/mixedcurl_exec(resource$ch)curl_close()函数声明:/**函数功能:关闭curl会话@param$chcurl_init()返回cURL句柄@returnvoid*/voidcurl_close(resource$ch)curl请求封装publicstaticfunctionparseApi($vars=Array(),$timeout=60,$uri=''){//初始化curl$ch=curl_init();curl_setopt($ch,CURLOPT_URL,$uri);//支持POST请求curl_setopt($ch,CURLOPT_POST,1);//不直接输出,返回变量curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//设置POST参数curl_setopt($ch,CURLOPT_POSTFIELDS,http_build_query($vars));//设置Timeout,防止机器被大量超时请求卡住curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);//请求数据$response=curl_exec($ch);//关闭请求curl_close($ch);//对数据进行编码,方便前后端数据处理$result=json_decode($response,true);//PHP返回数据return$result;}PHPcURL并行请求除了上面的curl_init,cURL还支持curl_multi_init并行请求,让我们同时请求数百个接口,而不是foreach轮询阻塞请求。具体可以参考我的另一篇文章:PHP实现并发请求。总结如果需要非阻塞请求,可以使用fsockopen()方法。常规使用curl来请求,功能强大,简单易用,按需配置。参考资料PHP手册file_get_contents:http://php.net/manual/zh/func...PHP手册stream_context_create:http://php.net/manual/zh/func...PHP手册fsockopen:http://php.net/manual/zh/func...百度百科curl:https://baike.baidu.com/item/...维基百科curl:https://zh.wikipedia.org/wiki...PHP手动curl功能:http://php.net/manual/zh/ref....博客园fsockopen实现异步请求:http://www.cnblogs.com/52fhy/...
