php – 什麼是鬥旅?
]
鬥旅
要開始你的初始問題,鬥旅只是一個名為userfilter.bucket旅的資源的名字.
你將通過兩個不同的旅作為第一和第二個引數到php_user_filter :: filter().第一旅是您讀取的輸入桶,第二旅最初是空的;你寫信給你
關於你的資料結構的更新…它真的只是一個雙重連結的列表基本上.但這可能是因為這個名字被偷走了;-)
stream_bucket_prepend()/ stream_bucket_append()
stream_bucket_prepend(resource $brigade, stdClass $bucket): null stream_bucket_append(resource $brigade, stdClass $bucket): null
預期的$旅是輸出旅,也是php_user_filter :: filter()的第二個引數.
$bucket是一個stdClass物件,它被stream_bucket_make_writable()或stream_bucket_new()返回).
這兩個功能只是將傳遞的桶新增到旅中.
stream_bucket_new()
要揭示這個功能,首先分析它的功能簽名是:
stream_bucket_new(resource $stream, string $buffer): stdClass
第一個引數是你正在寫這個桶的$stream.第二是這個新的桶將包含的$緩衝區.
[我想在這裡注意,$stream引數實際上不是很重要;它只是用於檢查我們是否需要永久分配記憶體,以便通過請求生存.我只是假設你可以通過傳遞永續性流在這裡,當在非永續性過濾器上執行時,使PHP很好的segfault …]
現在建立一個userfilter.bucket資源,該資源被分配給名為bucket的(stdClass)物件的屬性.
該物件還有另外兩個屬性:data和datalen,其中包含快取和緩衝區大小.
它將返回一個stdClass,您可以傳入stream_bucket_prepend()和stream_bucket_append().
stream_bucket_make_writable()
stream_bucket_make_writeable(resource $brigade): stdClass|null
它從$旅改變第一個桶,並返回它.如果$旅清空,它返回null.
進一步說明
當呼叫php_user_filter :: filter()時,呼叫物件filter()上的$stream屬性將被設定為我們當前正在處理的流.這也是您在呼叫它時傳遞給stream_bucket_new()的流. ($stream屬性將在呼叫後再次取消設定,不能在例如php_user_filter :: onClose())中重用它.
另請注意,即使您返回$datalen屬性,也不需要設定該屬性,以防在將資料傳遞到stream_bucket_prepend()或stream_bucket_append()之前更改$data屬性.
執行需要你(嗯,它會期望或將會發出一個警告),你在返回之前從$的桶中讀取所有的資料.
還有另一種情況,文件對我們說:在php_user_filter :: onCreate()中,$stream屬性未設定.只能在filter()方法呼叫期間設定.
通常,不要使用帶有非阻塞流的過濾器.我試過一次,這是非常錯誤的…And it’s not likely that’s ever going to be fixed…
總結(例子)
我們從最簡單的情況開始:寫回我們所得到的東西.
class simple_filter extends php_user_filter { function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } return PSFS_PASS_ON; } } stream_filter_register("simple", "simple_filter")
這裡發生的所有事情都是從桶中的桶中獲取桶,並將其重新放入$out鬥旅.
好的,現在嘗試操縱我們的輸入.
class reverse_filter extends php_user_filter { function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { $consumed += $bucket->datalen; $bucket->data = strrev($bucket->data); stream_bucket_prepend($out, $bucket); } return PSFS_PASS_ON; } } stream_filter_register("reverse", "reverse_filter")
現在我們註冊了相反的://協議,它會反轉你的字串(每個寫入在這裡都是自己的,而寫入順序仍然保留).所以,我們顯然現在需要操縱資料桶資料並在這裡新增.
現在,stream_bucket_new()的用例是什麼?通常你可以附加到$bucket->資料;是的,你甚至可以將所有的資料連線到第一個資料桶中,但是當flush()可能沒有什麼可以在鬥旅中,並且你想傳送一個最後一個數據桶,那麼你需要它.
class append_filter extends php_user_filter { public $stream; function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } // always append a terminating \n if ($closing) { $bucket = stream_bucket_new($this->stream, "\n"); stream_bucket_append($out, $bucket); } return PSFS_PASS_ON; } } stream_filter_register("append", "append_filter")
有了這個(以及關於
php_user_filter
class
的現有文件),應該能夠通過將所有這些強大的可能性結合到更強大的程式碼中,來進行各種魔術使用者流過濾.