这种协议有什么用呢?我们知道打算机中正常的协议有 http:// ,这是我们做web开拓最熟习的。还有 file:// 表示文件,ftp:// 表示ftp协议,当然,还有一些不太常用的 zlib:// 、 data:// 、 rar:// ,等等,这些协议PHP都是支持的,而且这些协议都是约定俗成的并且有相应的文件或流类型支持的协议。通过这些协议我们的程序可以读取、解析这些协议所对应的干系内容。比如说http协议,做事器、客户端浏览器都是由于支持了相同的http协议规范,以是才能够通过这个协议来进行传输,而传输的内容是什么呢?正是我们看到的网页或接口文本。而本日我们的主角 php:// 协议,实在也有另一个别名是 PHP伪协议 。伪协议的缘故原由实在便是这种协议只是PHP自身所支持的并定义的一种协议,而且也仅仅只是 IO 干系操作的一种协议规范。
好了,废话就说到这里,我们来一个一个的看看 php:// 干系的内容都有哪些。
while($line=fopen('php://stdin','r')){$info=fgets($line);echo$info;if($info=="exit\n"){break;}}while($info=fgets(STDIN)){echo$info;if($info=="exit\n"){break;}}
上述代码有什么用呢?相信做过 C 或者 Java 开拓的人会更有觉得,stdin 是获取PHP进程脚本的输入,也便是我们在利用命令行 php xxx.php 运行PHP脚本文件时,获取命令行输入内容的。上述代码便是利用 while 循环一贯监听命令行的输入,当你输入内容后进行打印,如果输入的是 exit 就退出循环也便是结束脚本的运行。

这里除了正常的用 fopen() 获取 php://stdin 句柄外,还利用了另一种办法,也便是第二个循环所展示的 STDIN 常量来方便快捷地直接获取输入内容。这也是PHP所推举的办法。同时,下面讲的 php://stdout 和 php://stderr ,也有相应的 STDOUT 和 STDERR 常量。
stdout 、 stderr 和 output 输出流$stdout=fopen('php://stdout','w');fputs($stdout,'fopen:stdout');echoPHP_EOL;file_put_contents("php://stdout","file_put_contents:stdout");echoPHP_EOL;file_put_contents("php://stderr","file_put_contents:stderr");echoPHP_EOL;$output=fopen('php://output','w');fputs($output,'fopen:output');echoPHP_EOL;file_put_contents("php://output","file_put_contents:output");echoPHP_EOL;
这三种都是输出流,实在就和 echo 、 print 一样,便是将内容打印输出的。不过不同的地方在于,stdin 和 stdout 是针对PHP命令行的输出。也便是说,如果我们是通过浏览器查看这个脚本的话,这两个输出的内容是不会打印到浏览器上的。小伙伴们可以试试用 php -S localhost:8081 <测试文件> 来测试下上述代码,访问 http://localhost:8081 的话,浏览器上会输出 output 打印的内容,而命令行这边则会打印 stdin 和 stdout 所输出的内容。
其余须要把稳的,这三个输出流都是只写的,而 stdin 是只读的。也便是说 file_get_contents() 对这三个输出流是没什么用的,而 file_put_contents() 对 stdin 流也是没效果的。
input 访问要求的原始数据的只读流这个相信做过接口开拓的大多数人都会打仗过。当前端或客户端利用 body raw 办法发送数据时,就利用这个协议来吸收POST中的原始 body 内容。
echofile_get_contents("php://input");
非常大略,这里我们直策应用 postman 来仿照这种要求,可以看我们是能够正常吸收到 body raw 里面的内容的。见下图:
memory 、 temp 内存及临时文件流$mem=fopen('php://memory','r+');for($i=0;$i<10;$i++){fwrite($mem,'fopen:memory');}rewind($mem);while($info=fgets($mem)){echo$info,PHP_EOL;}fclose($mem);
这两个流协议是输入、输出都支持的,它们都是在内存中读写数据。不同的是, php://temp 会在数据超过一定容量时将数据写到临时文件中。这里我们就不演示 temp 的操作了,它和 memory 的操作代码是非常像的。其余须要把稳的,它们两个操作都是一次性的,也便是说,如果我们在写入(fwrite)后直接关闭(fclose)了句柄,那么后面再读取的话(fgets),是无法获取到内容的。
filter 用于数据打开时的筛选过滤readfile("php://filter/read=string.toupper/resource=http://www.baidu.com");echofile_get_contents("php://filter/read=convert.base64-encode/resource=http://www.baidu.com");
这个自己试试就知道它的好处了,第一行我们是获取百度页面的内容,并把内容中所有的字母更换成大写字母了。第二个过滤器则是直接将百度首页的内容转成base64编码的内容了,是不是非常强大,我以为这个功能可以是我们好好开拓的一个能力。
总结实在说实话,笔者本人平常也便是用过 php://input 这一个协议而已,偶尔或者说基本一年难得用上几次 stdin 来进行脚本调试,但是,这并不妨碍我们理解学习这些流协议的利用。最紧张的是,通过学习后我们更进一步的理解了它们的浸染及适用的场景,这样就可以在将来须要的时候灵巧利用。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202003/source/%E5%85%B3%E4%BA%8EPHP%E6%B5%81%E4%B8%8D%E5%BE%97%E4%B8%8D%E8%AF%B4%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B.php
参考文档:
https://www.php.net/manual/zh/wrappers.php.php
https://www.php.net/manual/zh/filters.php