核心要點
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中文網其他相關文章!