首頁 >後端開發 >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