首页 >后端开发 >php教程 >PHP主| 了解PHP中的流

PHP主| 了解PHP中的流

Lisa Kudrow
Lisa Kudrow原创
2025-02-23 10:38:14695浏览

PHP Master | Understanding Streams in PHP

核心要点

  • PHP 流是强大的工具,用于泛化文件、网络和数据压缩操作。它们可以线性读取或写入,并且可以 fseek() 到流中的任意位置。每个流都有一个包装器,用于处理特定的协议或编码。
  • PHP 提供内置的包装器、协议和过滤器,并允许创建和注册自定义的包装器、协议和过滤器。默认包装器是 file://,每次访问文件系统时都会使用它。其他包装器包括 HTTP、Amazon S3、MS Excel、Google Storage、Dropbox 和 Twitter 的包装器。
  • 流上下文是特定于流的参数或选项,可以修改和增强包装器的行为。它们可以用来避免在简单的网络操作中使用 cURL,并且可以针对不同的用途单独修改或创建。流可用于为 PaaS 提供商创建虚拟文件系统包装器,并可用于为实现自定义文件格式和编码的应用程序构建自定义包装器和过滤器。

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 提供一些内置的包装器、协议和过滤器。要了解我们的机器上安装了哪些包装器,我们可以使用:

<code class="language-php"><?php
print_r(stream_get_transports());
print_r(stream_get_wrappers());
print_r(stream_get_filters());
?></code>

我的安装输出如下:

<code class="language-php"><?php
print_r(stream_get_transports());
print_r(stream_get_wrappers());
print_r(stream_get_filters());
?></code>

一套不错的工具,不是吗?此外,我们可以编写或使用针对 Amazon S3、MS Excel、Google Storage、Dropbox 甚至 Twitter 的第三方流。

php:// 包装器

PHP 有自己的包装器来访问语言的 I/O 流。有基本的 php://stdinphp://stdoutphp://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) 的结果将是:

<code class="language-bash">curl -d "Hello World" -d "foo=bar&name=John" http://localhost/dev/streams/php_input.php</code>

请注意,第一个数据包无法从 $_POST 数组访问。但是,如果我们改为使用 readfile('php://input'),我们将得到:

<code class="language-php">Array
(
    [foo] => bar
    [name] => John
)</code>

PHP 5.1 引入了 php://memoryphp://temp 流包装器,用于读取和写入临时数据。顾名思义,数据分别存储在内存中或由底层系统管理的临时文件中。还有 php://filter,这是一个元包装器,旨在在使用 readfile()file_get_contents()/stream_get_contents() 等函数打开流时应用过滤器。

<code>Hello World&foo=bar&name=John</code>

第一个示例使用过滤器对写入磁盘的数据进行编码,而第二个示例应用两个级联过滤器从远程 URL 读取数据。结果在我们的应用程序中可以从非常基本到非常强大。

流上下文

上下文是一组特定于流的参数或选项,可以修改和增强我们包装器的行为。一个常见的用途上下文是修改 HTTP 包装器。这让我们可以避免在简单的网络操作中使用 cURL。

<code class="language-php"><?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");
?></code>

首先,我们定义选项数组,这是一个数组的数组,格式为 $array['wrapper']['option_name'](可用的上下文选项根据具体的包装器而有所不同)。然后,我们调用 stream_context_get_default(),它返回默认上下文并接受一个可选的选项数组以应用。readfile() 语句使用这些设置来获取内容。在这个示例中,内容是在请求的主体中发送的,因此远程脚本将使用 php://input 来读取它。我们可以使用 apache_request_headers() 访问标头并获得:

<code class="language-php"><?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');
?></code>

我们修改了默认上下文选项,但是我们也可以创建替代上下文以单独使用。

<code class="language-php">Array
(
    [Host] => localhost
    [Auth] => SecretAuthToken
    [Content-type] => application/x-www-form-urlencoded
    [Content-length] => 11
)</code>

结论

我们如何在现实世界中利用流的力量?我们还可以去哪里?正如我们所看到的,流共享一些或所有与文件系统相关的函数,因此我想到的第一个用途是一系列虚拟文件系统包装器,用于与 Heroku 或 AppFog 等没有真实文件系统的 PaaS 提供商一起使用。只需很少的努力,我们就可以将我们的应用程序从标准托管服务移植到这些云服务,并享受其好处。此外——我将在后续文章中展示——我们可以为我们的应用程序构建自定义包装器和过滤器,这些应用程序实现了自定义文件格式和编码。

(由于篇幅限制,此处省略了FAQs部分。)

以上是PHP主| 了解PHP中的流的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn