转载请注明文章出处:https://tlanyan.me/php-review...PHP评测系列目录PH??P基础web请求cookieweb响应session数据库操作加解密Composer创建自己的Composer打包发送不管是哪种编程语言,IO操作都是值得学习和理解的。由于PHP的简单性,许多人可以在没有任何概念的情况下编写可用的代码。本文总结了PHP开发中几种常见的IO场景,并介绍了相应的操作,希望能帮助PHP开发者加深对IO的理解。后续文章将介绍隐藏在简单之下的本质:流。本文描述的场景包括:读写文件、命令行输入输出、与远程URL交互。事不宜迟,让我们开始吧!读写文件读写文件是最常见的IO操作。打开文件、读写内容、关闭文件,一气呵成,尿不出来。读取文件内容的典型例子:functiongetFileContent(string$filename):?string{if(!is_file($filename)){returnnull;}$fd=fopen($文件名,"rb");$content=fread($fd,filesize($filename);fclose($fd);return$content;}读写文件Soeasy!如果你想玩更高端的文件操作,至少要熟练在使用这些API时:file_exists/is_file/filesize/fileperms等辅助函数获取文件信息;fopen:打开一个文件,获取文件句柄,要弄清楚第二个参数(arwcbx)的含义;flock:获取一个文件lock,可用于实现进程互斥锁;fread/fgets/fscanf等函数获取文件内容;fwrite/fputs/fputcsv/ftruncate等函数写入内容;feof/ftell/fseek/rewind等操作文件指针位置的函数;fclose:关闭文件,释放资源。本节注意文件是指本地文件。对于远程文件,上述函数是否起作用取决于协议是否支持。例如fread/fwrite可以操作http://协议的资源,但是fustat/filesize等功能无法正常工作。可参考官网“ProtocolsandWrappers”查看非本地普通文件可用的功能信息。命令行输入输出PHP主要用于web开发,命令行应用也很常见,比如定时任务的脚本。在命令行模式下,与web开发有很多不同,比如使用多进程/线程(web中的curl_multiple不算),没有运行时间限制。使用命令行时,php_sapi_name的返回值为cli,标准输入输出指向终端(可以用ll/proc/进程号/fd查看)。PHP定义了三个句柄常量:STDIN:标准输入,只读,相当于用fopen打开“php://stdin”;STDOUT:标准输出,只写,相当于用fopen打开“php://stdout”;STDERR:标准错误输出,只写,相当于fopen打开“php://stderr”。注意标准输入对应的是“php://stdin”而不是“php://input”,虽然两者在命令行模式下的行为几乎一样(区别可以参考我之前的文章php://output和php://stdout的区别)。操作三个读写通道,对应的函数有fread/fgetc/fscanf/fwrite/fputc/fputs等,PHP会在脚本执行完毕后关闭这三个流,无需用户手动关闭。下面的代码简要展示了用法:functionprompt(string$message):string{fwrite(STDOUT,$message);//fgets也会读取换行符,可以通过rtrim过滤掉returnrtrim(fgets(STDIN));}functionprintln(string$message):void{fputs(STDOUT,$message.PHP_EOL);}函数错误(string$message):void{fputs(STDERR,$message.PHP_EOL);}$value=prompt("inputyourvalue:");if($value!==""){println("yourinput:$value");}else{error("invalidvalue!");}命令行方式"php://output"链接到标准输出,所以可以正常使用echo/print/var_dump等输出函数。要交互式地从命令行获取输入,需要使用文件读取函数,例如fread/fgets。常量PHP_EOL是预定义的跨平台换行符。EOL是endofline的缩写,不是endoflife~与远程URL交互获取网页内容,cURL扩展绝对值得一提。如果熟悉curl命令,就应该了解其强大的功能,应该能够游刃有余地使用PHP中的CURL系列功能。与远程网站交互是一个请求和响应的过程。具体可以参考我之前的文章:PHPReviewWebRequest和PHPReviewWebResponse,也可以参考HTTP协议的权威文档。使用CURL与远程Web服务器交互的过程如下:初始化CURL句柄,设置请求信息:请求URL、头信息、cookie、文本等;发送请求获取执行结果关闭CURL句柄,释放资源CURL简单易用,缺点是请求设置参数复杂,不易记忆。在实践中,建议以类似Java的HttpClient库的形式与远程服务器进行交互。HttpClient类库提取了请求、响应、传输的概念,完全面向对象,更加语义化。使用它可以更好地促进对HTTP协议的理解。缺点是代码比较繁琐。PHP中有很多类似的HTTP请求库。下面是一个在Yii2中使用yii2-httpclient类库的例子:useyii\httpclient\Client;useyii\httpclient\Response;$url="https://tlanyan.me";$data=["key1"=>"value1","key2"=>"value2",];$response=(newClient())->createRequest()->setMethod("POST")->setFormat(Client::FORMAT_JSON)->setUrl($url)->setData($data)->send();if($response->isOk){$response->setFormat(Client::FORMAT_JSON);//获取解析后的数据$data=$response->data;....}使用fopen/fsocketopen等函数也可以实现与远程服务器的交互,这部分内容将在后续流程中进行讲解。file_get_contents废话了半天,还没讲PHP获取内容的神器:file_get_contents函数。这个功能是PHP读取内容当之无愧的神器,不管是普通文件,php://,http://,还是标准输入等,file_get_contents一句就搞定。与Java等语言的client/connection/stream等一堆代码相比,file_get_contents体现了PHP简单实用的设计理念。想必这个功能在PHP开发中比较常用,所以我就用几个简单的例子来结束这篇文章(注意代码中的POST请求页面已经涉及到了流的内容)。//读取普通文件file_get_contents("/etc/passwd");//获取web请求的原始文本,可以获取json/xml等数据格式的原始内容,也可以获取上传的文件。注意返回可能只是Binary//与json/xml数据格式交互时,建议使用此方法代替$GLOBALS['HTTP_RAW_POST_DATA'],$HTTP_RAW_POST_DATA已在PHP7.2file_get_contents("php://input");//获取URL的内容,可以替代curlfile_get_contents('https://tlanyan.me');//传入context对象,可以实现post请求$contextOptions=["http"=>["method"=>"POST","ignore_errors"=>true,"content"=>"username=tlanyan","header"=>"Content-type:application/x-www-form-urlencoded","user_agent"=>"MySpider/1.0",],"ssl"=>["verify_peer"=>false,],];$context=stream_context_create($contextOptions);file_get_contents("https://tlanyan.me",false,$context);//cli模式接下来,从标准输入读取数据。此时换行符也被视为输入的一部分,应该以ctrl+d作为结束输入的标志file_get_contents(STDIN);//写入文件内容file_put_contents("foo.txt","测试函数调用\n",FILE_APPEND);参考http://php.net/manual/en/ref....http://php.net/manual/en/feat...http://php.net/manual/en/book...https://github.com/yiisoft/yi...感谢阅读,感谢指正!
