最近使用stream進行一些項目的開發,在使用到stream bucket時,查閱了google還是國內的百度,發現網上關于stream bucket的介紹文章很少,如php.net的官方手冊對于這一塊也沒有具體的文檔,也沒有很詳細地介紹這個bucket在stream中的作用。最多出現可用信息也就是stream_bucket_append — Append bucket to brigade、stream_bucket_make_writeable — Return a bucket object from the brigade for operating on、stream_bucket_new — Create a new bucket for use on the current stream、stream_bucket_prepend。 相信很多Phper在閱讀到這里也會有一些困惑,特別是使用到php_user_filter時必然會接觸到bucket。因此我將自己一些理解和應用實例記錄下來,同時我也希望跟各位能有進一步的溝通,可以email我,lailaiji@163.com(賴來基)。
在PHP中,可以將文件、網絡、數據壓縮等操作資源對象可以視為一個stream流對象,通過統一流操作實現對這些對象的抽象和封裝,方便我們處理相關資源對象。這篇博文就沒有涉及展開對流的細節講解,而是側重通過講解php_user_filter帶來對于stream bucket的一些認識。
回到本文的正題,一開始我們需要先了解清楚兩個概念,Bucket(桶)及Brigade(隊列)。這里可以理解為裝載數據的一個對象,該對象包含數據內容(data)及數據長度(datalen),相當于我們把流數據裝到這個桶里來,該桶除了有數據還有數據的高度;而Brigade呢,則是這些桶的一個隊列,從而組織成為一個數據流,這個隊列可以是一個或者多個桶組成。
理解了上面的概念,我們通過自定義的一個filter來分步講解這兩個概念。
新建一個test_custom_filter.php
class foo extends php_user_filter { public function filter($in, $out, &$consumed, $closing) { $bucket = stream_bucket_make_writeable($in); if($bucket) { $consumed += $bucket->datalen; $_f = fopen("php://temp",'w'); $new_bucket = stream_bucket_new($_f, ''); $string = $bucket->data."I am lailaiji\n"; $new_bucket->data=ucfirst($string); fclose($_f); stream_bucket_append($out, $new_bucket); } //數據處理成功,可供其它管道讀取 return PSFS_PASS_ON; } } stream_filter_register('test', 'foo'); $data = file_get_contents('php://filter/read=test/resource=data.txt'); echo $data;
而data.txt文件
hello
運行php -f test_custom_filter.php得到如下
Hello I am lailaiji
自定義的filter需要繼承基類php_user_filter,并且重寫filter方法,這個方法共有四個參數
$in
: 指向輸入流隊列
$out
:指向輸出流隊列
$consumed
: 引用方式傳遞,必須增加了轉換數據的長度
$closing
: 如果最后一個bucket或者即將關閉時,可以設置為true
認識第一個函數:stream_bucket_make_writeable($bregade)
用途:將隊列里的每個bucket取出,得到一個bucket對象。
$bucket = stream_bucket_make_writeable($in);
該方法可以得到我們從data.txt文件中的內容,可以通過調用bucket對象屬性$bucket->data
第二個函數:stream_bucket_new($handle,$buffer)
用途:產生一個指定流的bucket對象,一般來說,我們都會使用臨時php://temp進行操作流數據
第三個函數:stream_bucket_append($handle,$bucket) 或者stream_bucket_prepend($handle,$bucket)
用途,將bucket對象追加到隊列里
stream_bucket_append($out, $new_bucket);
上面通過這個方法將我們的bucket追加到輸出流($out),因此我們可以通過file_get_contents獲得輸出內容
另外php_user_filter還定義了三個常量
PSFS_PASS_ON:過濾器處理成功,輸出流有可用數據返回
PSFS_FEED_ME:過濾器處理成功,但是沒有數據返回
PSFS_ERR_FATAL:默認返回值,有錯誤,不返回
還有一點需要說明的是:
如果仔細的讀者在使用php_user_filter,會發現filter函數必然后運行兩次或者兩次以上,明明我只有一個輸入流,怎么會被運行兩次呢?后來仔細分析了才發現最后一次運行是由于最后一個bucket即將關閉時,也就是closing的值為true的時候被調起,為整理關閉前做一些處理,此時輸入流輸出為空
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。