2016-05-31 190 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