mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-16 17:08:54 +00:00

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@146336 c90b9560-bf6c-de11-be94-00142212c4b1
319 lines
10 KiB
XML
Executable file
319 lines
10 KiB
XML
Executable file
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!-- $Revision: 1.9 $ -->
|
|
<!-- Author: Wez Furlong <wez@thebrainroom.com>
|
|
Please contact me before making any major amendments to the
|
|
content of this section. Splitting/Merging are fine if they are
|
|
required for php-doc restructuring purposes - just drop me a line
|
|
if you make a change (so I can update my local copy).
|
|
-->
|
|
|
|
<chapter id="streams">
|
|
<title>Streams API for PHP Extension Authors</title>
|
|
|
|
<sect1 id="streams.overview">
|
|
<title>Overview</title>
|
|
<para>
|
|
The PHP Streams API introduces a unified approach to the handling of
|
|
files and sockets in PHP extension. Using a single API with standard
|
|
functions for common operations, the streams API allows your extension
|
|
to access files, sockets, URLs, memory and script-defined objects.
|
|
Streams is a run-time extensible API that allows dynamically loaded
|
|
modules (and scripts!) to register new streams.
|
|
</para>
|
|
<para>
|
|
The aim of the Streams API is to make it comfortable for developers to
|
|
open files, URLs and other streamable data sources with a unified API
|
|
that is easy to understand. The API is more or less based on the ANSI
|
|
C stdio family of functions (with identical semantics for most of the main
|
|
functions), so C programmers will have a feeling of familiarity with streams.
|
|
</para>
|
|
<para>
|
|
The streams API operates on a couple of different levels: at the base level,
|
|
the API defines php_stream objects to represent streamable data sources.
|
|
On a slightly higher level, the API defines php_stream_wrapper objects
|
|
which "wrap" around the lower level API to provide support for retrieving
|
|
data and meta-data from URLs. An additional <literal>context</literal>
|
|
parameter, accepted by most stream creation functions, is passed to the
|
|
wrapper's <literal>stream_opener</literal> method to fine-tune the behavior
|
|
of the wrapper.
|
|
</para>
|
|
<para>
|
|
Any stream, once opened, can also have any number of <literal>filters</literal>
|
|
applied to it, which process data as it is read from/written to the stream.
|
|
</para>
|
|
<para>
|
|
Streams can be cast (converted) into other types of file-handles, so that they
|
|
can be used with third-party libraries without a great deal of trouble. This
|
|
allows those libraries to access data directly from URL sources. If your
|
|
system has the <function>fopencookie</function> or
|
|
<function>funopen</function> function, you can even
|
|
pass any PHP stream to any library that uses ANSI stdio!
|
|
</para>
|
|
<para>
|
|
<note>
|
|
<para>
|
|
The functions in this chapter are for use in the PHP source code and
|
|
are not PHP functions. Userland stream functions can be found in the
|
|
<link linkend="ref.stream">Stream Reference</link>.
|
|
</para>
|
|
</note>
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="streams.basics">
|
|
<title>Streams Basics</title>
|
|
<para>
|
|
Using streams is very much like using ANSI stdio functions. The main
|
|
difference is in how you obtain the stream handle to begin with.
|
|
In most cases, you will use <function>php_stream_open_wrapper</function>
|
|
to obtain the stream handle. This function works very much like fopen,
|
|
as can be seen from the example below:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>simple stream example that displays the PHP home page</title>
|
|
<programlisting role="c">
|
|
<![CDATA[
|
|
php_stream * stream = php_stream_open_wrapper("http://www.php.net", "rb", REPORT_ERRORS, NULL);
|
|
if (stream) {
|
|
while(!php_stream_eof(stream)) {
|
|
char buf[1024];
|
|
|
|
if (php_stream_gets(stream, buf, sizeof(buf))) {
|
|
printf(buf);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
php_stream_close(stream);
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
The table below shows the Streams equivalents of the more common ANSI stdio functions.
|
|
Unless noted otherwise, the semantics of the functions are identical.
|
|
<table>
|
|
<title>ANSI stdio equivalent functions in the Streams API</title>
|
|
<tgroup cols="3">
|
|
<thead>
|
|
<row>
|
|
<entry>ANSI Stdio Function</entry>
|
|
<entry>PHP Streams Function</entry>
|
|
<entry>Notes</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
|
|
<row>
|
|
<entry>fopen</entry>
|
|
<entry>php_stream_open_wrapper</entry>
|
|
<entry>Streams includes additional parameters</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fclose</entry>
|
|
<entry>php_stream_close</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fgets</entry>
|
|
<entry>php_stream_gets</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fread</entry>
|
|
<entry>php_stream_read</entry>
|
|
<entry>The nmemb parameter is assumed to have a value of 1, so the prototype looks more like read(2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fwrite</entry>
|
|
<entry>php_stream_write</entry>
|
|
<entry>The nmemb parameter is assumed to have a value of 1, so the prototype looks more like write(2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fseek</entry>
|
|
<entry>php_stream_seek</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>ftell</entry>
|
|
<entry>php_stream_tell</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>rewind</entry>
|
|
<entry>php_stream_rewind</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>feof</entry>
|
|
<entry>php_stream_eof</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fgetc</entry>
|
|
<entry>php_stream_getc</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fputc</entry>
|
|
<entry>php_stream_putc</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fflush</entry>
|
|
<entry>php_stream_flush</entry>
|
|
<entry></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>puts</entry>
|
|
<entry>php_stream_puts</entry>
|
|
<entry>Same semantics as puts, NOT fputs</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>fstat</entry>
|
|
<entry>php_stream_stat</entry>
|
|
<entry>Streams has a richer stat structure</entry>
|
|
</row>
|
|
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="streams.resources">
|
|
<title>Streams as Resources</title>
|
|
<para>
|
|
All streams are registered as resources when they are created. This ensures
|
|
that they will be properly cleaned up even if there is some fatal error.
|
|
All of the filesystem functions in PHP operate on streams resources - that
|
|
means that your extensions can accept regular PHP file pointers as
|
|
parameters to, and return streams from their functions.
|
|
The streams API makes this process as painless as possible:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>How to accept a stream as a parameter</title>
|
|
<programlisting role="c">
|
|
<![CDATA[
|
|
PHP_FUNCTION(example_write_hello)
|
|
{
|
|
zval *zstream;
|
|
php_stream *stream;
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream))
|
|
return;
|
|
|
|
php_stream_from_zval(stream, &zstream);
|
|
|
|
/* you can now use the stream. However, you do not "own" the
|
|
stream, the script does. That means you MUST NOT close the
|
|
stream, because it will cause PHP to crash! */
|
|
|
|
php_stream_write(stream, "hello\n");
|
|
|
|
RETURN_TRUE();
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>How to return a stream from a function</title>
|
|
<programlisting role="c">
|
|
<![CDATA[
|
|
PHP_FUNCTION(example_open_php_home_page)
|
|
{
|
|
php_stream *stream;
|
|
|
|
stream = php_stream_open_wrapper("http://www.php.net", "rb", REPORT_ERRORS, NULL);
|
|
|
|
php_stream_to_zval(stream, return_value);
|
|
|
|
/* after this point, the stream is "owned" by the script.
|
|
If you close it now, you will crash PHP! */
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Since streams are automatically cleaned up, it's tempting to think that we can get
|
|
away with being sloppy programmers and not bother to close the streams when we
|
|
are done with them. Although such an approach might work, it is not a good idea
|
|
for a number of reasons: streams hold locks on system resources while they are
|
|
open, so leaving a file open after you have finished with it could prevent other
|
|
processes from accessing it. If a script deals with a large number of files,
|
|
the accumulation of the resources used, both in terms of memory and the
|
|
sheer number of open files, can cause web server requests to fail. Sounds
|
|
bad, doesn't it? The streams API includes some magic that helps you to
|
|
keep your code clean - if a stream is not closed by your code when it should
|
|
be, you will find some helpful debugging information in you web server error
|
|
log.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Always use a debug build of PHP when developing an extension
|
|
(<option>--enable-debug</option> when running configure), as a lot of
|
|
effort has been made to warn you about memory and stream leaks.
|
|
</simpara>
|
|
</note>
|
|
<para>
|
|
In some cases, it is useful to keep a stream open for the duration of a request,
|
|
to act as a log or trace file for example. Writing the code to safely clean up
|
|
such a stream is not difficult, but it's several lines of code that are not
|
|
strictly needed. To save yourself the trouble of writing the code, you
|
|
can mark a stream as being OK for auto cleanup. What this means is
|
|
that the streams API will not emit a warning when it is time to auto-cleanup
|
|
a stream. To do this, you can use <function>php_stream_auto_cleanup</function>.
|
|
</para>
|
|
</sect1>
|
|
|
|
|
|
&chapters.streams.common;
|
|
&chapters.streams.dir;
|
|
&chapters.streams.file;
|
|
&chapters.streams.socket;
|
|
&chapters.streams.structs;
|
|
&chapters.streams.constants;
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"../../manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|
|
|