核心要点
fseek()
到流中的任意位置。每个流都有一个包装器,用于处理特定的协议或编码。file://
,每次访问文件系统时都会使用它。其他包装器包括 HTTP、Amazon S3、MS Excel、Google Storage、Dropbox 和 Twitter 的包装器。PHP 流是 PHP 提供的资源,我们经常透明地使用它们,但它们也可以成为非常强大的工具。通过学习如何利用它们的力量,我们可以将我们的应用程序提升到更高的水平。PHP 手册对流有很好的描述:> 流是在 PHP 4.3.0 中引入的,作为一种泛化文件、网络、数据压缩和其他操作的方法,这些操作共享一组通用的函数和用途。简单来说,流是一个表现出可流行为的资源对象。也就是说,它可以线性地读取或写入,并且可能能够 fseek()
到流中的任意位置。
每个流都有一个实现包装器,它包含处理特定协议或编码所需的附加代码。PHP 提供一些内置的包装器,我们可以轻松创建和注册自定义的包装器。我们甚至可以使用上下文和过滤器来修改或增强包装器的行为。
流基础知识
流的引用格式为 <scheme>://<target></target></scheme>
。<scheme></scheme>
是包装器的名称,<target></target>
将根据包装器的语法而有所不同。默认包装器是 file://
,这意味着每次访问文件系统时我们都会使用流。例如,我们可以编写 readfile('/path/to/somefile.txt')
或 readfile('file:///path/to/somefile.txt')
,并获得相同的结果。如果我们改为使用 readfile('http://google.com/')
,那么我们告诉 PHP 使用 HTTP 流包装器。如前所述,PHP 提供一些内置的包装器、协议和过滤器。要了解我们的机器上安装了哪些包装器,我们可以使用:
<?php print_r(stream_get_transports()); print_r(stream_get_wrappers()); print_r(stream_get_filters()); ?>
我的安装输出如下:
<?php print_r(stream_get_transports()); print_r(stream_get_wrappers()); print_r(stream_get_filters()); ?>
一套不错的工具,不是吗?此外,我们可以编写或使用针对 Amazon S3、MS Excel、Google Storage、Dropbox 甚至 Twitter 的第三方流。
php:// 包装器
PHP 有自己的包装器来访问语言的 I/O 流。有基本的 php://stdin
、php://stdout
和 php://stderr
包装器映射默认的 I/O 资源,我们还有 php://input
,这是一个具有 POST 请求原始主体的只读流。当我们处理将数据有效负载放在 POST 请求主体内的远程服务时,这非常方便。让我们使用 cURL 进行快速测试:
<code>Array ( [0] => tcp [1] => udp [2] => unix [3] => udg [4] => ssl [5] => sslv3 [6] => sslv2 [7] => tls ) Array ( [0] => https [1] => ftps [2] => compress.zlib [3] => compress.bzip2 [4] => php [5] => file [6] => glob [7] => data [8] => http [9] => ftp [10] => zip [11] => phar ) Array ( [0] => zlib.* [1] => bzip2.* [2] => convert.iconv.* [3] => string.rot13 [4] => string.toupper [5] => string.tolower [6] => string.strip_tags [7] => convert.* [8] => consumed [9] => dechunk [10] => mcrypt.* [11] => mdecrypt.* )</code>
响应 PHP 脚本中 print_r($_POST)
的结果将是:
curl -d "Hello World" -d "foo=bar&name=John" http://localhost/dev/streams/php_input.php
请注意,第一个数据包无法从 $_POST
数组访问。但是,如果我们改为使用 readfile('php://input')
,我们将得到:
Array ( [foo] => bar [name] => John )
PHP 5.1 引入了 php://memory
和 php://temp
流包装器,用于读取和写入临时数据。顾名思义,数据分别存储在内存中或由底层系统管理的临时文件中。还有 php://filter
,这是一个元包装器,旨在在使用 readfile()
或 file_get_contents()
/stream_get_contents()
等函数打开流时应用过滤器。
<code>Hello World&foo=bar&name=John</code>
第一个示例使用过滤器对写入磁盘的数据进行编码,而第二个示例应用两个级联过滤器从远程 URL 读取数据。结果在我们的应用程序中可以从非常基本到非常强大。
流上下文
上下文是一组特定于流的参数或选项,可以修改和增强我们包装器的行为。一个常见的用途上下文是修改 HTTP 包装器。这让我们可以避免在简单的网络操作中使用 cURL。
<?php // 写入编码数据 file_put_contents("php://filter/write=string.rot13/resource=file:///path/to/somefile.txt","Hello World"); // 读取数据并进行编码/解码 readfile("php://filter/read=string.toupper|string.rot13/resource=http://www.google.com"); ?>
首先,我们定义选项数组,这是一个数组的数组,格式为 $array['wrapper']['option_name']
(可用的上下文选项根据具体的包装器而有所不同)。然后,我们调用 stream_context_get_default()
,它返回默认上下文并接受一个可选的选项数组以应用。readfile()
语句使用这些设置来获取内容。在这个示例中,内容是在请求的主体中发送的,因此远程脚本将使用 php://input
来读取它。我们可以使用 apache_request_headers()
访问标头并获得:
<?php $opts = array( 'http' => array( 'method' => "POST", 'header' => "Auth: SecretAuthToken\r\n" . "Content-type: application/x-www-form-urlencoded\r\n" . "Content-length: " . strlen("Hello World"), 'content' => 'Hello World' ) ); $default = stream_context_get_default($opts); readfile('http://localhost/dev/streams/php_input.php'); ?>
我们修改了默认上下文选项,但是我们也可以创建替代上下文以单独使用。
Array ( [Host] => localhost [Auth] => SecretAuthToken [Content-type] => application/x-www-form-urlencoded [Content-length] => 11 )
结论
我们如何在现实世界中利用流的力量?我们还可以去哪里?正如我们所看到的,流共享一些或所有与文件系统相关的函数,因此我想到的第一个用途是一系列虚拟文件系统包装器,用于与 Heroku 或 AppFog 等没有真实文件系统的 PaaS 提供商一起使用。只需很少的努力,我们就可以将我们的应用程序从标准托管服务移植到这些云服务,并享受其好处。此外——我将在后续文章中展示——我们可以为我们的应用程序构建自定义包装器和过滤器,这些应用程序实现了自定义文件格式和编码。
(由于篇幅限制,此处省略了FAQs部分。)
以上是PHP主| 了解PHP中的流的详细内容。更多信息请关注PHP中文网其他相关文章!