I am trying to create a "virtual" file without using either memory or a temporary file. The "virtual" file needs to pass a check made with file_exists()
while not throwing any error or warning when used with require
or include
.
Allows you to implement your own protocol handlers and streams for use with all the other filesystem functions (such as
fopen()
,fread()
etc.).
…where file_exists()
is one of them. The docs page states:
As of PHP 5.0.0, this function can also be used with some URL wrappers. Refer to Supported Protocols and Wrappers to determine which wrappers support
stat()
family of functionality.
My attempt there was to build 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 the method, file_exists()
does not execute any stream class method.
How could I get a virtual stream wrapper to work (with file_exists()
)?
I am fully aware that tempnam( __DIR__, '' )
will pass both:
var_dump( tempnam( __DIR__, '' ) );
Returns true
require tempnam( __DIR__, '' );
No errorbut I do not want to use a temporary file as there might be a better way (performance wise).
It looks like you just need to implement a public url_stat()
method on VirtualFileWrapper
for it to pass the file_exists()
check.
To silence warnings and errors from include
and require
, you must implement 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";
Take care to pass file_exists()
a string, rather than the resource you created with fopen()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With