stream_register_wrapper

(PHP 4 >= 4.3.0, PHP 5)

stream_register_wrapper -- 註冊一個用 PHP 類實現的 URL 封裝協定

說明

boolean stream_register_wrapper ( string protocol, string classname )

stream_register_wrapper() 容許會員實現自訂的協定處理器和流,用於所有其它的檔案系統函數中(例如 fopen()fread() 等)。

要實現一個封裝協定,需要按照如下定義聲明一個包括有一些函數的類。當有人對你的流使用 fopen 時,PHP 將建立一個 classname 的案例並呼叫該案例的方法。必須嚴格按照如下的描述實現方法 - 否則將導致不明確的行為。

若果 protocol 已經有了處理協定,則 stream_register_wrapper() 將返回 FALSE

boolean stream_open ( string path, string mode, int options, string opened_path )

當你的流物件被建立之後立即會呼叫此方法。path 指定了傳入 fopen() 以及此物件需要取回的 URL。可以用 parse_url() 來將此 URL 分割成幾部分。

mode 用來開啟檔案的模式,和 fopen() 中的一樣。你有責任檢查 mode 對於所請求的 path 是否合法。

options 儲存了通過流 API 設定的附加標誌。可以儲存以下一個值或是用 OR 合併的多個值。

標誌說明
STREAM_USE_PATH若果 path 是相對路徑,則用 include_path 搜尋資源。
STREAM_REPORT_ERRORS若果設定了本標誌,你有責任在開啟流時用 trigger_error() 來喚起錯誤。若果沒有設定這個標誌,那麼你不需要喚起任何錯誤。

若果成功開啟了 path,並且在 options 中設定了 STREAM_USE_PATH,你需要將 opened_path 設定為實際被開啟的檔案/資源的完整路徑。

若果成功開啟了所請求的資源,應該返回 TRUE,否則返回 FALSE

void stream_close ( void )

本方法在流關閉時被呼叫,使用 fclose()。必須釋放被流鎖定或配置的任何資源。

string stream_read ( int count )

當對流進行 fread()fgets() 動作時本方法被呼叫。必須從現用的讀寫位置以字串返回最多 count 位元組的資料。若果可用資料少於 count 位元組,則返回盡可能多的資料。若果沒有可供返回的資料,返回 FALSE 或是空字串。必須用成功讀取的位元組數去更新流的讀寫位置。

int stream_write ( string data )

當對流進行 fwrite() 動作時本方法被呼叫。必須將 data 儲存到你的流使用的底層存儲空間去。若果沒有足夠的空間了,則試著儲存盡可能多的位元組。應該返回成功被儲存入流的位元組數,或是沒有儲存時返回 0。必須用成功寫入的位元組數去更新流的讀寫位置。

boolean stream_eof ( void )

當對流進行 feof() 動作時本方法被呼叫。若果讀寫位置到了流的盡頭或是沒有更多資料可讀時返回 TRUE,否則返回 FALSE

int stream_tell ( void )

當對流進行 ftell() 動作時本方法被呼叫。應該返回流的現用的讀寫位置。

boolean stream_seek ( int offset, int whence )

當對流進行 fseek() 動作時本方法被呼叫。應該根據 offsetwhence 來更新流的讀寫位置。這些參數的更多訊息見 fseek()。若果位置成功更新了則返回 TRUE,否則返回 FALSE

boolean stream_flush ( void )

當對流進行 fflush() 動作時本方法被呼叫。若果你在流中暫存了資料還沒有寫入底層存儲空間時,那現在應該做了。若果暫存資料被成功儲存(或沒有資料可供儲存)時返回 TRUE,當資料無法被儲存時返回 FALSE

下面的例子實現了一個 var:// 協定處理器,可以容許使用標準的檔案系統流函數來對特殊的全局變量進行讀寫動作,例如 fread()。var:// 協定的實現如下,給出 url "var://foo" 將可以讀寫 $GLOBALS["foo"]。

例子 1. 讀寫全局變量的流

class VariableStream {
    var $position;
    var $varname;
   
    function stream_open($path, $mode, $options, &$opened_path)
    {
        $url = parse_url($path);
        $this->varname = $url["host"];
        $this->position = 0;
        
        return true;
    }

    function stream_read($count)
    {
        $ret = substr($GLOBALS[$this->varname], $this->position, $count);
        $this->position += strlen($ret);
        return $ret;
    }

    function stream_write($data)
    {
        $left = substr($GLOBALS[$this->varname], 0, $this->position);
        $right = substr($GLOBALS[$this->varname], $this->position + strlen($data));
        $GLOBALS[$this->varname] = $left . $data . $right;
        $this->position += strlen($data);
        return strlen($data);
    }

    function stream_tell()
    {
        return $this->position;
    }

    function stream_eof()
    {
        return $this->position >= strlen($GLOBALS[$this->varname]);
    }

    function stream_seek($offset, $whence)
    {
        switch($whence) {
            case SEEK_SET:
                if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {
                     $this->position = $offset;
                     return true;
                } else {
                     return false;
                }
                break;
                
            case SEEK_CUR:
                if ($offset >= 0) {
                     $this->position += $offset;
                     return true;
                } else {
                     return false;
                }
                break;
                
            case SEEK_END:
                if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {
                     $this->position = strlen($GLOBALS[$this->varname]) + $offset;
                     return true;
                } else {
                     return false;
                }
                break;
                
            default:
                return false;
        }
    }
}

stream_register_wrapper("var", "VariableStream")
    or die("Failed to register protocol");

$myvar = "";
    
$fp = fopen("var://myvar", "r+");

fwrite($fp, "line1\n");
fwrite($fp, "line2\n");
fwrite($fp, "line3\n");

rewind($fp);
while(!feof($fp)) {
    echo fgets($fp)
}
fclose($fp);
var_dump($myvar);