2016-05-31 188 views
5

我正在嘗試在不使用內存或臨時文件的情況下創建「虛擬」文件。當使用requireinclude時,「虛擬」文件需要通過file_exists()進行檢查,同時不會發出任何錯誤或警告。如何創建虛假/「虛擬」文件?

允許你實現自己的協議處理程序,並與all the other filesystem functions(如fopen()fread()等)流使用。

...其中file_exists()就是其中之一。 The docs page指出:

從PHP 5.0.0開始,這個函數也可以和一些URL包裝一起使用。請參閱Supported Protocols and Wrappers以確定哪些包裝器支持stat()功能族。

我嘗試有建立一個自定義,虛擬文件​​包

class VirtualFileWrapper 
{ 
    public $context; 

    public function stream_open($path, $mode, $options, &$opened_path) 
    { 
     return TRUE; 
    } 

    public function stream_stat() 
    { 
     var_dump(__METHOD__); 
     $data = [ 
      'dev'  => 0, 
      'ino'  => getmyinode(), 
      'mode' => 'r', 
      'nlink' => 0, 
      'uid'  => getmyuid(), 
      'gid'  => getmygid(), 
      'rdev' => 0, 
      'size' => 0, 
      'atime' => time(), 
      'mtime' => getlastmod(), 
      'ctime' => FALSE, 
      'blksize' => 0, 
      'blocks' => 0, 
     ]; 
     return array_merge(array_values($data), $data); 
    } 
} 

stream_wrapper_register('virtual', 'VirtualFileWrapper'); 

$file = fopen("virtual://foo", 'r+'); 

// Executes VirtualFileWrapper::stream_stat() 
fstat($file); 

// Executes no VirtualFileWrapper method 
file_exists($file); 

雖然fstat()函數執行的方法,file_exists()不執行任何流類方法。

我怎麼能得到一個虛擬的流封裝到(與file_exists())工作?


我充分認識到tempnam(__DIR__, '')將通過兩種:

  • var_dump(tempnam(__DIR__, ''));返回true
  • require tempnam(__DIR__, '');沒有錯誤

,但我不想使用臨時文件,因爲可能是更好的方式(性能明智)。

+1

你不能。 file_exists()需要一個字符串作爲其參數。你可以傳入一個實現魔術__toString()方法的對象,但是file_exists會將這個字符串作爲'stat()'並失敗,因爲這個文件並不存在。 –

+0

@MarcB其實[** Drupal **有這個工作](http://drupal.stackexchange.com/a/24233/55237)。我只是無法弄清楚vfsStream是如何在源代碼中混淆的。 – kaiser

+0

你爲什麼試圖完成這個?我認爲創建一個假文件是一個非常奇怪的做法。 – Jehy

回答

5

看起來您只需要在VirtualFileWrapper上實施公開url_stat()方法,以便通過file_exists()檢查。

要消除警告和錯誤從includerequire,你必須實現stream_read()stream_eof()方法:

class VirtualFileWrapper 
{ 
    public $context; 

    public function stream_open($path, $mode, $options, &$opened_path) 
    { 
     return TRUE; 
    } 

    public function stream_stat() 
    { 
     var_dump(__METHOD__); 
     return []; 
    } 

    public function url_stat() 
    { 
     return array (
      0 => 0, 
      1 => 0, 
      2 => 0, 
      3 => 0, 
      4 => 0, 
      5 => 0, 
      6 => 0, 
      7 => 0, 
      8 => 0, 
      9 => 0, 
      10 => 0, 
      11 => 0, 
      12 => 0, 
      'dev' => 0, 
      'ino' => 0, 
      'mode' => 0, 
      'nlink' => 0, 
      'uid' => 0, 
      'gid' => 0, 
      'rdev' => 0, 
      'size' => 0, 
      'atime' => 0, 
      'mtime' => 0, 
      'ctime' => 0, 
      'blksize' => 0, 
      'blocks' => 0 
     ); 
    } 

    public function stream_read(){ 
     return ''; 
    } 

    public function stream_eof(){ 
     return ''; 
    } 

} 

stream_wrapper_register('virtual', 'VirtualFileWrapper'); 

$file = fopen("virtual://foo", 'r+'); 

// Executes VirtualFileWrapper::stream_stat() 
fstat($file); 

// Executes no VirtualFileWrapper method 
file_exists("virtual://foo"); 

//Still no errors :-)! 
require "virtual://foo"; 
include "virtual://foo"; 

小心通過file_exists()一個字符串,而不是你fopen()創建的資源。

+0

我希望我能提供更多的細節 - 我不知道爲什麼這個工程,我回來,編輯,如果我知道了。 – HPierce

+0

經過幾個小時的試用後,我真的很高興你跳進去了:除了事實,我在'url_stat()'裏面返回'stat()',我的例子與你的沒有什麼不同。看起來我需要學會閱讀:P ['return' value](http://php.net/manual/en/streamwrapper.url-stat.php)明確指出。萬分感謝!順便說一句,另一個奇怪的是,'require'作爲'include'在我的本地測試中被調用_twice_。 – kaiser