Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document details of output buffering / output control #3126

Merged
merged 4 commits into from Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions reference/outcontrol/book.xml
Expand Up @@ -22,6 +22,9 @@

&reference.outcontrol.setup;
&reference.outcontrol.constants;
&reference.outcontrol.output-buffering;
&reference.outcontrol.flushing-system-buffers;
&reference.outcontrol.user-level-output-buffers;
&reference.outcontrol.examples;
&reference.outcontrol.reference;

Expand Down
156 changes: 156 additions & 0 deletions reference/outcontrol/flushing-system-buffers.xml
@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<chapter xml:id="outcontrol.flushing-system-buffers" xmlns="http://docbook.org/ns/docbook">
<section>
<title>Flushing System Buffers</title>
<para>
PHP provides two related ways
to flush (send and discard the contents of) system buffers:
through calling <function>flush</function>
and through enabling implicit flushing
with <function>ob_implicit_flush</function>
or the <link linkend="ini.implicit-flush">implicit_flush</link>
&php.ini; setting.
</para>
<para>
With implicit flushing disabled, PHP will flush output only
when <function>flush</function> is called or when the script ends.
</para>
<para>
With implicit flushing enabled, PHP will attempt to flush
after every block of code resulting in output.
Output in this context is non-zero length data that is:
<itemizedlist xml:id="outputcontrol.what-is-output">
<listitem>
<simpara>
outside of the <literal>&#60;?php ?&#62;</literal> tags
Girgias marked this conversation as resolved.
Show resolved Hide resolved
</simpara>
</listitem>
<listitem>
<simpara>
printed by language constructs and functions
whose explicit purpose is to output user provided variables or strings such as
<function>echo</function>, <function>print</function>,
<function>printf</function>, <function>var_dump</function>,
<function>var_export</function>, <function>vprintf</function>
</simpara>
</listitem>
<listitem>
<simpara>
printed by functions whose purpose is to collect and output
data/information on the running script or PHP such as
<function>debug_print_backtrace</function>, <function>phpcredits</function>,
<function>phpinfo</function>,
<methodname>ReflectionExtension::info</methodname>
</simpara>
</listitem>
<listitem>
<simpara>
printed by PHP on an uncaught exception or an unhandled error
(subject to the settings of
<link linkend="ini.display-errors">display_errors</link>
and <link linkend="ini.error-reporting">error_reporting</link>)
</simpara>
</listitem>
<listitem>
<simpara>
anything written to <literal>php://output</literal>
</simpara>
</listitem>
</itemizedlist>
</para>
<note>
<simpara>
Printing empty strings or sending headers is not considered output
and will not result in a flush operation.
</simpara>
</note>
<warning>
<simpara>
If implicit flushing is enabled, control characters
(e.g. <literal>"\n"</literal>, <literal>"\r"</literal>,
<literal>"\0"</literal>)
will trigger flushing as well.
</simpara>
</warning>
</section>

<section>
<title>Limitations</title>
<para>
This functionality cannot flush user-level output buffers.
To use these together, user-level output buffers must be flushed
before flushing system buffers in order for PHP to produce any output.
</para>
<warning>
<simpara>
Calling <function>flush</function> or implicit flushing being enabled
can interfere with output handlers of user-level output buffers
that set and send headers in a web context
(e.g. <function>ob_gzhandler</function>)
by sending headers before these handlers can do so.
</simpara>
</warning>
<para>
Buffering implemented by the underlying software/hardware
cannot be overridden by PHP and should be taken into account
when working with PHP's buffer control functions.
Checking the web servers/browsers/consoles buffering settings
and working with these can alleviate possible issues.
Working in a web context, either the web server's buffering settings
or the script's buffering could be adjusted to work in tandem
whereas working around the buffering strategies of various browsers
can be achieved by adjusting buffering in the PHP script.
On consoles that implement line buffering,
newline characters could be inserted in the appropriate places
before flushing output.
</para>
</section>

<section>
<title><acronym>SAPI</acronym> Differences In Flushing</title>
<para>
Although flushing is implemented by each <acronym>SAPI</acronym>
in a slightly different way,
these implementations fall in one of two categories:
<itemizedlist>
<listitem>
<simpara>
<acronym>SAPI</acronym>s used in a web context will flush headers first
followed by the output.
<literal>Apache2Handler</literal>, <literal>CGI</literal>,
<literal>FastCGI</literal> and <literal>FPM</literal>
are such <acronym>SAPI</acronym>s
</simpara>
</listitem>
<listitem>
<simpara>
other <acronym>SAPI</acronym>s
such as <literal>CLI</literal> and <literal>embed</literal>
will flush output only
</simpara>
</listitem>
</itemizedlist>
</para>
</section>

</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:"~/.phpdoc/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
-->
115 changes: 115 additions & 0 deletions reference/outcontrol/output-buffering.xml
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<chapter xml:id="outcontrol.output-buffering" xmlns="http://docbook.org/ns/docbook">
<section>
<title>Output Buffering</title>
<para>
Output buffering is the buffering (temporary storage) of output
before it is flushed (sent and discarded) to the browser (in a web context)
or to the shell (on the command line).
While output buffering is active no output is sent from the script,
instead the output is stored in an internal buffer.
</para>
</section>

<section>
<title>Buffering Affecting PHP</title>
<para>
PHP relies on the underlying software/hardware infrastructure
when flushing output.
Buffering implemented by consoles on the command line (e.g. line buffered)
or web servers and browser in a web context (e.g. fully buffered)
do affect when output is displayed to the end-user.
Some of these effects can be eliminated by fine-tuning server settings
and/or aligning buffer sizes of the various layers.
</para>
</section>

<section>
<title>Output Buffering Control In PHP</title>
<para>
PHP provides a fully buffered user-level output buffer
with functions to start, manipulate and turn off the buffer
(most <link linkend="ref.outcontrol">ob_<replaceable>*</replaceable></link> functions),
and two functions to flush the underlying system buffers
(<function>flush</function> and <function>ob_implicit_flush</function>).
Some of this functionality can be set and/or configured
using the appropriate &php.ini; settings as well.
</para>
</section>

<section>
<title>Use Cases</title>
<para>
Output buffering is generally useful in situations when the buffered output
is modified or inspected, or it is used more than once in a request;
or when the controlled flushing of output is desired.
Specific use cases include:
<itemizedlist>
<listitem>
<simpara>
caching the result of compute/time intensive scripts
for example by generating static <literal>HTML</literal> pages
</simpara>
</listitem>
<listitem>
<simpara>
re-using the generated output by displaying it, saving it to a file
and/or sending it by email
</simpara>
</listitem>
<listitem>
<simpara>
flushing the <literal>head</literal> of an <literal>HTML</literal> page
separate from the <literal>body</literal> allows browsers
to load external resources while the script executes
potentially more time consuming processes
(e.g. database/file access, external network connection).
This is only useful if the <literal>HTTP</literal> status code
cannot change after the headers are sent
</simpara>
</listitem>
<listitem>
<simpara>
extracting information from functions that would otherwise produce output
(e.g. <function>phpinfo</function>)
</simpara>
</listitem>
<listitem>
<simpara>
controlling the output of third-party code by modifying/using parts
(e.g. extracting data, replacing words/phrases,
adding missing <literal>HTML</literal> tags),
or discarding it entirely under certain conditions (e.g. errors)
</simpara>
</listitem>
<listitem>
<simpara>
polyfilling certain unavailable web server functionality
(e.g. compressing or encoding output)
</simpara>
</listitem>
</itemizedlist>
</para>
</section>

</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:"~/.phpdoc/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
-->