Php file stream wrapper

# Streams

A stream wrapper provides a handler for one or more specific schemes.

The example below shows a simple stream wrapper that sends PATCH HTTP requests when the stream is closed.

// register the FooWrapper class as a wrapper for foo:// URLs. stream_wrapper_register("foo", FooWrapper::class, STREAM_IS_URL) or die("Duplicate stream wrapper registered"); class FooWrapper  // this will be modified by PHP to show the context passed in the current call. public $context; // this is used in this example internally to store the URL private $url; // when fopen() with a protocol for this wrapper is called, this method can be implemented to store data like the host. public function stream_open(string $path, string $mode, int $options, string &$openedPath) : bool  $url = parse_url($path); if($url === false) return false; $this->url = $url["host"] . "/" . $url["path"]; return true; > // handles calls to fwrite() on this stream public function stream_write(string $data) : int  $this->buffer .= $data; return strlen($data); > // handles calls to fclose() on this stream public function stream_close()  $curl = curl_init("http://" . $this->url); curl_setopt($curl, CURLOPT_POSTFIELDS, $this->buffer); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PATCH"); curl_exec($curl); curl_close($curl); $this->buffer = ""; > // fallback exception handler if an unsupported operation is attempted. // this is not necessary. public function __call($name, $args)  throw new \RuntimeException("This wrapper does not support $name"); > // this is called when unlink("foo://something-else") is called. public function unlink(string $path)  $url = parse_url($path); $curl = curl_init("http://" . $url["host"] . "/" . $url["path"]); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_exec($curl); curl_close($curl); > > 

This example only shows some examples of what a generic stream wrapper would contain. These are not all methods available. A full list of methods that can be implemented can be found at http://php.net/streamWrapper

# Syntax

# Parameters

# Remarks

Streams are essentially a transfer of data between an origin and a destination, to paraphrase Josh Lockhart in his book Modern PHP.

The origin and the destination can be

  • a file
  • a command-line process
  • a network connection
  • a ZIP or TAR archive
  • temporary memory
  • standard input/output

or any other resource available via PHP’s stream wrappers

Examples of available stream wrappers ( schemes ):

  • file:// — Accessing local filesystem
  • http:// — Accessing HTTP(s) URLs
  • ftp:// — Accessing FTP(s) URLs
  • php:// — Accessing various I/O streams
  • phar:// — PHP Archive
  • ssh2:// — Secure Shell 2
  • ogg:// — Audio streams

The scheme (origin) is the identifier of the stream’s wrapper. For example, for the file system this is file:// . The target is the stream’s data source, for example the file name.

Источник

stream_wrapper_register

Позволяет вам реализовать ваши собственные обработчики протоколов и потоков для использования со всеми другими функциями файловой системы (такими как fopen() , fread() и т.д.).

Список параметров

Название регистрируемой обёртки. Допустимые имена протоколов должны содержать только буквы, цифры, точки (.), плюсы (+) или дефисы (-).

Название класса, который реализует протокол protocol .

Должно быть установлено в STREAM_IS_URL , если параметр protocol является протоколом URL. По умолчанию 0, локальный поток.

Возвращаемые значения

Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.

stream_wrapper_register() будет возвращать false , если протокол protocol уже имеет обработчик.

Примеры

Пример #1 Как зарегистрировать обёртку потока

$existed = in_array ( «var» , stream_get_wrappers ());
if ( $existed ) stream_wrapper_unregister ( «var» );
>
stream_wrapper_register ( «var» , «VariableStream» );
$myvar = «» ;

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

if ( $existed ) stream_wrapper_restore ( «var» );
>

Результат выполнения данного примера:

line1 line2 line3 string(18) "line1 line2 line3 "

Смотрите также

  • Класс-прототип streamWrapper
  • Пример класса, зарегистрированного в качестве обёртки потока
  • stream_wrapper_unregister() — Отменяет регистрацию обёртки URL
  • stream_wrapper_restore() — Восстанавливает отменённую ранее встроенную обёртку
  • stream_get_wrappers() — Получить список зарегистрированных потоков

User Contributed Notes 13 notes

If you plan to use your wrapper in a require_once you need to define stream_stat(). If you plan to allow any other tests like is_file()/is_dir(), you have to define url_stat().

stream_stat() must define the size of the file, or it will never be included. url_stat() must define mode, or is_file()/is_dir()/is_executable(), and any of those functions affected by clearstatcache() simply won’t work.

It’s not documented, but directories must be a mode like 040777 (octal), and files a mode like 0100666. If you wish the file to be executable, use 7s instead of 6s. The last 3 digits are exactly the same thing as what you pass to chmod. 040000 defines a directory, and 0100000 defines a file. It would be really helpful to add this to the official manual!

Updated. I figured there’s no need to store the variable name if we’re dereferenceing; we can just store the pointer and not have to dereference in each function for brevity.

Also, I added the assertion that the stream is a string, since we’re behaving basically like it has to be, and I changed the name to GlobalStream and global://, as that’s a more descriptive moniker than VariableName/var://.
class GlobalStream private $pos ;
private $stream ;
public function stream_open ( $path , $mode , $options , & $opened_path ) $url = parse_url ( $path );
$this -> stream = & $GLOBALS [ $url [ «host» ]];
$this -> pos = 0 ;
if (! is_string ( $this -> stream )) return false ;
return true ;
>
public function stream_read ( $count ) $p =& $this -> pos ;
$ret = substr ( $this -> stream , $this -> pos , $count );
$this -> pos += strlen ( $ret );
return $ret ;
>
public function stream_write ( $data ) $l = strlen ( $data );
$this -> stream =
substr ( $this -> stream , 0 , $this -> pos ) .
$data .
substr ( $this -> stream , $this -> pos += $l );
return $l ;
>
public function stream_tell () return $this -> pos ;
>
public function stream_eof () return $this -> pos >= strlen ( $this -> stream );
>
public function stream_seek ( $offset , $whence ) $l = strlen ( $this -> stream );
switch ( $whence ) case SEEK_SET : $newPos = $offset ; break;
case SEEK_CUR : $newPos = $this -> pos + $offset ; break;
case SEEK_END : $newPos = $l + $offset ; break;
default: return false ;
>
$ret = ( $newPos >= 0 && $newPos if ( $ret ) $this -> pos = $newPos ;
return $ret ;
>
>
stream_wrapper_register ( ‘global’ , ‘GlobalStream’ ) or die( ‘Failed to register protocol global://’ );

$fp = fopen ( «global://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 );
?>

Updated for PHP 5, and optimized for readability, low line count, and minimum memory use:

class VariableStream private $position ;
private $varname ;
public function stream_open ( $path , $mode , $options , & $opened_path ) $url = parse_url ( $path );
$this -> varname = $url [ «host» ];
$this -> position = 0 ;
return true ;
>
public function stream_read ( $count ) $p =& $this -> position ;
$ret = substr ( $GLOBALS [ $this -> varname ], $p , $count );
$p += strlen ( $ret );
return $ret ;
>
public function stream_write ( $data ) $v =& $GLOBALS [ $this -> varname ];
$l = strlen ( $data );
$p =& $this -> position ;
$v = substr ( $v , 0 , $p ) . $data . substr ( $v , $p += $l );
return $l ;
>
public function stream_tell () return $this -> position ;
>
public function stream_eof () return $this -> position >= strlen ( $GLOBALS [ $this -> varname ]);
>
public function stream_seek ( $offset , $whence ) $l = strlen (& $GLOBALS [ $this -> varname ]);
$p =& $this -> position ;
switch ( $whence ) case SEEK_SET : $newPos = $offset ; break;
case SEEK_CUR : $newPos = $p + $offset ; break;
case SEEK_END : $newPos = $l + $offset ; break;
default: return false ;
>
$ret = ( $newPos >= 0 && $newPos if ( $ret ) $p = $newPos ;
return $ret ;
>
>
stream_wrapper_register ( «var» , «VariableStream» )
or die( «Failed to register protocol» );

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

In response to Anonymouse at Coward dot com:

The manual says «Reading stops when up to length bytes have been read, [. ] or (after opening userspace stream) when 8192 bytes have been read whichever comes first.»

I tested it and fread($filehandle, 4096) returns 4096 bytes, so it’s working as the manual says it should. You’re right when you say «8192 bytes is always passed to stream_read as count», but that doesn’t mean fread will return 8192 bytes. If you call fread twice with length 4096, PHP calls stream_read passing 8192 as count on the first fread, and doesn’t call it on second fread. On both cases, fread returns the correct amount of bytes.

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 ;

function stream_read ( $count )
echo «stream_read called asking for $count bytes\n» ;
$ret = substr ( $GLOBALS [ $this -> varname ], $this -> position , $count );
$this -> position += strlen ( $ret );
return $ret ;
>

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

stream_wrapper_register ( «var» , «VariableStream» )
or die( «Failed to register protocol» );

$myvar = «» ;
$l = range ( ‘a’ , ‘z’ );
for( $i = 0 ; $i < 65536 ; $i ++) $myvar .= $l [ array_rand ( $l )];
>

while (! feof ( $fp )) $out = fread ( $fp , 1000 );
echo «fread returned » , strlen ( $out ), » bytes\n» ;
>

Источник

streamWrapper::stream_open

This method is called immediately after the wrapper is initialized (f.e. by fopen() and file_get_contents() ).

Parameters

Specifies the URL that was passed to the original function.

Note:

The URL can be broken apart with parse_url() . Note that only URLs delimited by :// are supported. : and :/ while technically valid URLs, are not.

The mode used to open the file, as detailed for fopen() .

Note:

Remember to check if the mode is valid for the path requested.

Holds additional flags set by the streams API. It can hold one or more of the following values OR’d together.

Flag Description
STREAM_USE_PATH If path is relative, search for the resource using the include_path.
STREAM_REPORT_ERRORS If this flag is set, you are responsible for raising errors using trigger_error() during opening of the stream. If this flag is not set, you should not raise any errors.

If the path is opened successfully, and STREAM_USE_PATH is set in options , opened_path should be set to the full path of the file/resource that was actually opened.

Return Values

Returns true on success or false on failure.

Errors/Exceptions

Emits E_WARNING if call to this method fails (i.e. not implemented).

Notes

Note:

The streamWrapper::$context property is updated if a valid context is passed to the caller function.

See Also

Источник

Читайте также:  Unexpected strict mode reserved word typescript
Оцените статью