How to create a fake / "virtual" file?

I am trying to create a "virtual" file without using memory or a temporary file. A "virtual" file should pass the test done using file_exists() without causing any errors or warnings when used with require or include .

Allows you to implement your own handlers and protocol threads for use with all other file system functions (for example, fopen() , fread() , etc.).

... where file_exists() is one of them. The documentation page states:

Starting with PHP 5.0.0, this function can also be used with some URL wrappers. Refer to Supported Protocols and Wrappers to determine which shells support the stat() family of functions.

My attempt to create a custom virtual file wrapper

 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 ); 

While the fstat() function executes this method, file_exists() does not execute any stream class method.

How can I make a virtual thread wrapper work (with file_exists() )?


I fully understand that tempnam( __DIR__, '' ) will go through both:

  • var_dump( tempnam( __DIR__, '' ) ); Returns true
  • require tempnam( __DIR__, '' ); Error

but I do not want to use a temporary file, as there may be a better way (in terms of performance).

+5
source share
1 answer

It looks like you just need to implement the public url_stat() method on VirtualFileWrapper so that it passes the file_exists() check.

To disable warnings and errors from include and require , you must implement the stream_read() and stream_eof() methods:

 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"; 

Try passing the file_exists() string, not the resource created with fopen() .

+5
source

All Articles