Web студия "GrandView"
  Главная   Написать Контакты
   
   
О проекте
Руководство php
 

ob_start

(PHP 4, PHP 5)

ob_start -- Turn on output buffering

Description

bool ob_start ( [callback output_callback [, int chunk_size [, bool erase]]] )

This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.

The contents of this internal buffer may be copied into a string variable using ob_get_contents(). To output what is stored in the internal buffer, use ob_end_flush(). Alternatively, ob_end_clean() will silently discard the buffer contents.

An optional output_callback function may be specified. This function takes a string as a parameter and should return a string. The function will be called when ob_end_flush() is called, or when the output buffer is flushed to the browser at the end of the request. When output_callback is called, it will receive the contents of the output buffer as its parameter and is expected to return a new output buffer as a result, which will be sent to the browser. If the output_callback is not a callable function, this function will return FALSE. If the callback function has two parameters, the second parameter is filled with a bit-field consisting of PHP_OUTPUT_HANDLER_START, PHP_OUTPUT_HANDLER_CONT and PHP_OUTPUT_HANDLER_END. If output_callback returns FALSE original input is sent to the browser.

Замечание: In PHP 4.0.4, ob_gzhandler() was introduced to facilitate sending gz-encoded data to web browsers that support compressed web pages. ob_gzhandler() determines what type of content encoding the browser will accept and will return its output accordingly.

Замечание: Before PHP 4.3.2 this function did not return FALSE in case the passed output_callback can not be executed.

Внимание

Some web servers (e.g. Apache) change the working directory of a script when calling the callback function. You can change it back by e.g. chdir(dirname($_SERVER['SCRIPT_FILENAME'])) in the callback function.

If the optional parameter chunk_size is passed, the callback function is called on every first newline after chunk_size bytes of output. The output_callback parameter may be bypassed by passing a NULL value.

If the optional parameter erase is set to FALSE, the buffer will not be deleted until the script finishes (as of PHP 4.3.0).

Output buffers are stackable, that is, you may call ob_start() while another ob_start() is active. Just make sure that you call ob_end_flush() the appropriate number of times. If multiple output callback functions are active, output is being filtered sequentially through each of them in nesting order.

ob_end_clean(), ob_end_flush(), ob_clean(), ob_flush() and ob_start() may not be called from a callback function. If you call them from callback function, the behavior is undefined. If you would like to delete the contents of a buffer, return "" (a null string) from callback function. You can't even call functions using the output buffering functions like print_r($expression, true) or highlight_file($filename, true) from a callback function.

Пример 1. User defined callback function example

<?php

function callback($buffer)
{
 
// replace all the apples with oranges
 
return (str_replace("apples", "oranges", $buffer));
}

ob_start("callback");

?>
<html>
<body>
<p>It's like comparing apples to oranges.</p>
</body>
</html>
<?php

ob_end_flush
();

?>

Would produce:

<html>
<body>
<p>It's like comparing oranges to oranges.</p>
</body>
</html>

See also ob_get_contents(), ob_end_flush(), ob_end_clean(), ob_implicit_flush(), ob_gzhandler(), ob_iconv_handler() mb_output_handler(), and ob_tidyhandler().



output_add_rewrite_var> <ob_list_handlers
Last updated: Sat, 27 Jan 2007
 
add a note add a note User Contributed Notes
ob_start
Anonymous
22-Oct-2007 06:40
As a follow up to my previous post :
(output seems to go to standard ouptput in command  line mode even with the use of output buffering (ob_start) )

Setting implicit_flush to false seems to do the trick :

   ini_set('implicit_flush',false); // (avoids output even with    ob_start, in command line mode)
   ob_start();
   include (realpath(dirname(__FILE__))."/".$template);
   $ret_str.=ob_get_contents();
   ob_end_clean();
   ini_set('implicit_flush',true);

(See :
Chapter 43. Using PHP from the command line
)
Francois Hill
22-Oct-2007 05:42
Following clement dot ayme at st dot com 's remark :

In my experience it seems that the output IS buffered, but ALSO sent to the standard output !
Charlie Farrow
18-Oct-2007 09:49
Under certain freak conditions, when an error ocours perfoming an action on an object that cannot be done (either because the object does not exist or the method does not exist) inside of an ob_start() the script will exit and print everything the current function generates before the error, but nothing else, including no error message.

I am at a loss to why no error message appears and am trying to get a working example for the developers that is simpler than my whole program!

So if you are using ob_start() and you get no output, check your objects.... you have made a mistake on them somewhere. The only trouble is you will not know where as there is no error!!
Asher Haig (ahaig at ridiculouspower dot com)
20-Aug-2007 01:17
When a script ends, all buffered output is flushed (this is not a bug: http://bugs.php.net/bug.php?id=42334&thanks=4). What happens when the script throws an error (and thus ends) in the middle of an output buffer? The script spits out everything in the buffer before printing the error!

Here is the simplest solution I have been able to find. Put it at the beginning of the error handling function to clear all buffered data and print only the error:

$handlers = ob_list_handlers();
while ( ! empty($handlers) )    {
    ob_end_clean();
    $handlers = ob_list_handlers();
}
clement dot ayme at st dot com
27-Jul-2007 09:51
ob_start() seems not compliant with command-line PHP.

just calling the function ahead of your unix-php script and nothing
happens. The STDOUT stream is not buffered.
tracey AT archive DOT org
29-Mar-2007 02:01
Way to make all stdout and stderr write to a log
from *inside* a php script.
You simply need to make sure to call elog() every
once in awhile to get output.
It's a nice way to "daemonize" a script w.r.t. its logging.

// This allows us to capture all stdout and stderr (and error_log() calls)
// to this logfile...
// The "collected output" will be flushed anytime "elog()" is used...
ini_set("error_log", "/var/log/script.log");
ob_start();

function elog($str)
{
  // get anything written to stdout or stderr that did *NOT* use elog()
  // and write it now...
  $writeme = ob_get_contents();
  if ($writeme)
  {
    error_log($writeme);
    ob_end_clean();
    ob_start();
  }
  // now write message this method was called with
  error_log($str);
}
joebezucha at tlen dot pl
16-Mar-2007 03:05
Hi, I use those functions for stripping unnecessary chars in my output code...because I have JavaScript placed in outpout code so I don't remove \n\r\t but just replace them with single space (it could cause errors in scripts)
Function stripBufferSkipTextareaTags skips tags Textarea. It's needed to don't loose \n\r when user edit some content...

sorry for my english ;)

<?php

function stripBufferSkipTextareaTags($buffer){
   
$poz_current = 0;
   
$poz_end = strlen($buffer)-1;
   
$result = "";
   
    while (
$poz_current < $poz_end){
       
$t_poz_start = stripos($buffer, "<textarea", $poz_current);
        if (
$t_poz_start === false){
           
$buffer_part_2strip = substr($buffer, $poz_current);
           
$temp = stripBuffer($buffer_part_2strip);
           
$result .= $temp;
           
$poz_current = $poz_end;
        }
        else{
           
$buffer_part_2strip = substr($buffer, $poz_current, $t_poz_start-$poz_current);
           
$temp = stripBuffer($buffer_part_2strip);
           
$result .= $temp;
           
$t_poz_end = stripos($buffer, "</textarea>", $t_poz_start);
           
$temp = substr($buffer, $t_poz_start, $t_poz_end-$t_poz_start);
           
$result .= $temp;
           
$poz_current = $t_poz_end;
        }
    }
    return
$result;
}

function
stripBuffer($buffer){
   
// change new lines and tabs to single spaces
   
$buffer = str_replace(array("\r\n", "\r", "\n", "\t"), ' ', $buffer);
   
// multispaces to single...
   
$buffer = ereg_replace(" {2,}", ' ',$buffer);
   
// remove single spaces between tags
   
$buffer = str_replace("> <", "><", $buffer);
   
// remove single spaces around &nbsp;
   
$buffer = str_replace(" &nbsp;", "&nbsp;", $buffer);
   
$buffer = str_replace("&nbsp; ", "&nbsp;", $buffer);
    return
$buffer;
}

ob_start("stripBufferSkipTextareaTags");

?>
denis at SPAM_WELCOME dot i39 dot ru
13-Mar-2007 07:55
This function's behaviour  has been changed in php 5.2.0:

<?
global $AP;
$AP = new ap;
ob_start("ob_end");

function ob_end() {
        global $AP;
        $r = $AP->test();

        return $r;
}

class ap {
        function test() {
                return "debug";
        }
}
?>

In older versions it shows: "debug".
But latest php version causes error: PHP Fatal error: Call to a member function test() on a non-object.
And this is not a bug: http://bugs.php.net/bug.php?id=40104
Tobias Goldkamp
25-Dec-2006 03:02
I use this to strip unnecessary characters from HTML output:

<?php

function sanitize_output($buffer)
{
   
$search = array(
       
'/\>[^\S ]+/s', //strip whitespaces after tags, except space
       
'/[^\S ]+\</s', //strip whitespaces before tags, except space
       
'/(\s)+/s'  // shorten multiple whitespace sequences
       
);
   
$replace = array(
       
'>',
       
'<',
       
'\\1'
       
);
 
$buffer = preg_replace($search, $replace, $buffer);
    return
$buffer;
}

ob_start("sanitize_output");

?>
lucky760 at yahoo dot com
21-Nov-2006 09:20
Just for simplicity's sake (and because I had to rewrite it for use at http://www.VideoSift.com anyway), here's a very simplified, pre-PHP5 version. Just add one call to dump_css_cache() for each of your CSS files.

<?php

ob_start
('ob_gzhandler');

header('Content-Type: text/css; charset: UTF-8');
header('Cache-Control: must-revalidate');

$expire_offset = 0; // set to a reaonable interval, say 3600 (1 hr)
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire_offset) . ' GMT');

function
css_compress($buffer) {
 
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);// remove comments
 
$buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  '), '', $buffer);// remove tabs, spaces, newlines, etc.
 
$buffer = str_replace('{ ', '{', $buffer);// remove unnecessary spaces.
 
$buffer = str_replace(' }', '}', $buffer);
 
$buffer = str_replace('; ', ';', $buffer);
 
$buffer = str_replace(', ', ',', $buffer);
 
$buffer = str_replace(' {', '{', $buffer);
 
$buffer = str_replace('} ', '}', $buffer);
 
$buffer = str_replace(': ', ':', $buffer);
 
$buffer = str_replace(' ,', ',', $buffer);
 
$buffer = str_replace(' ;', ';', $buffer);
  return
$buffer;
}

function
dump_css_cache($filename) {
 
$cwd = getcwd() . DIRECTORY_SEPARATOR;

 
$stat = stat($filename);
 
$current_cache = $cwd . '.' . $filename . '.' . $stat['size'] . '-' . $stat['mtime'] . '.cache';

 
// the cache exists - just dump it
 
if (is_file($current_cache)) {
    include(
$current_cache);
    return;
  }

 
// remove any old, lingering caches for this file
 
if ($dead_files = glob($cwd . '.' . $filename . '.*.cache', GLOB_NOESCAPE))
    foreach (
$dead_files as $dead_file)
     
unlink($dead_file);
 
  if (!
function_exists('file_put_contents')) {
    function
file_put_contents($filename, $contents) {
     
$handle = fopen($filename, 'w');
     
fwrite($handle, $contents);
     
fclose($handle);
    }
  }
 
 
$cache_contents = css_compress(file_get_contents($filename));
 
file_put_contents($current_cache, $cache_contents);
 
  echo
$cache_contents;
}

dump_css_cache('_general.css');

?>
lucky760 at yahoo dot com
21-Nov-2006 09:10
In extension to the compress() function posted below, here's a nifty little class that improves the idea a bit. Basically, running that compress() function for all your CSS for every single page load is clearly far less than optimal, especially since the styles will change only infrequently at the very worst.

With this class you can simply specify an array of your CSS file names and call dump_style(). The contents of each file are saved in compress()'d form in a cache file that is only recreated when the corresponding source CSS changes.

It's intended for PHP5, but will work identically if you just un-OOP everything and possibly define file_put_contents.

Enjoy!

<?php

$CSS_FILES
= array(
 
'_general.css'
);

$css_cache = new CSSCache($CSS_FILES);
$css_cache->dump_style();

//
// class CSSCache
//

class CSSCache {
  private
$filenames = array();
  private
$cwd;
   
  public function
__construct($i_filename_arr) {
    if (!
is_array($i_filename_arr))
     
$i_filename_arr = array($i_filename_arr);
   
   
$this->filenames = $i_filename_arr;
   
$this->cwd = getcwd() . DIRECTORY_SEPARATOR;
   
    if (
$this->style_changed())
     
$expire = -72000;
    else
     
$expire = 3200;
   
   
header('Content-Type: text/css; charset: UTF-8');
   
header('Cache-Control: must-revalidate');
   
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire) . ' GMT');
  }
 
  public function
dump_style() {
   
ob_start('ob_gzhandler');
   
    foreach (
$this->filenames as $filename)
     
$this->dump_cache_contents($filename);
   
   
ob_end_flush();
  }
 
    private function
get_cache_name($filename, $wildcard = FALSE) {
   
$stat = stat($filename);
    return
$this->cwd . '.' . $filename . '.' .
      (
$wildcard ? '*' : ($stat['size'] . '-' . $stat['mtime'])) . '.cache';
  }
 
  private function
style_changed() {
    foreach (
$this->filenames as $filename)
      if (!
is_file($this->get_cache_name($filename)))
        return
TRUE;
    return
FALSE;
  }

  private function
compress($buffer) {
   
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
   
$buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  '), '', $buffer);
   
$buffer = str_replace('{ ', '{', $buffer);
   
$buffer = str_replace(' }', '}', $buffer);
   
$buffer = str_replace('; ', ';', $buffer);
   
$buffer = str_replace(', ', ',', $buffer);
   
$buffer = str_replace(' {', '{', $buffer);
   
$buffer = str_replace('} ', '}', $buffer);
   
$buffer = str_replace(': ', ':', $buffer);
   
$buffer = str_replace(' ,', ',', $buffer);
   
$buffer = str_replace(' ;', ';', $buffer);
    return
$buffer;
  }
 
  private function
dump_cache_contents($filename) {
   
$current_cache = $this->get_cache_name($filename);
   
   
// the cache exists - just dump it
   
if (is_file($current_cache)) {
      include(
$current_cache);
      return;
    }
   
   
// remove any old, lingering caches for this file
   
if ($dead_files = glob($this->get_cache_name($filename, TRUE), GLOB_NOESCAPE))
      foreach (
$dead_files as $dead_file)
       
unlink($dead_file);
   
   
$compressed = $this->compress(file_get_contents($filename));
   
file_put_contents($current_cache, $compressed);
   
    echo
$compressed;
  }
}

?>
10-Nov-2006 10:34
I'm sure some of you more brilliant minds could pare this down some more, but using the method found at fiftyfoureleven.com  for compressing, I got my 10090-byte stylesheet down to 3536 bytes and then again down to 2713 bytes, by stripping unecessary characters from the stylesheet. 2 ob_start calls and the CSS file is now 73% smaller. YMMV.

<?php
ob_start
("ob_gzhandler");
ob_start("compress");
header("Content-type: text/css; charset: UTF-8");
header("Cache-Control: must-revalidate");
$off = 0; # Set to a reaonable value later, say 3600 (1 hr);
$exp = "Expires: " . gmdate("D, d M Y H:i:s", time() + $off) . " GMT";
header($exp);

function
compress($buffer) {
   
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer); // remove comments
   
$buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer); // remove tabs, spaces, newlines, etc.
   
$buffer = str_replace('{ ', '{', $buffer); // remove unnecessary spaces.
   
$buffer = str_replace(' }', '}', $buffer);
   
$buffer = str_replace('; ', ';', $buffer);
   
$buffer = str_replace(', ', ',', $buffer);
   
$buffer = str_replace(' {', '{', $buffer);
   
$buffer = str_replace('} ', '}', $buffer);
   
$buffer = str_replace(': ', ':', $buffer);
   
$buffer = str_replace(' ,', ',', $buffer);
   
$buffer = str_replace(' ;', ';', $buffer);
    return
$buffer;
}

require_once(
'screen.css');
require_once(
'layout.css');
require_once(
'custom.php');
require_once(
'titles.css');
require_once(
'bus.css');

?>
feedback at realitymedias dot com
07-Nov-2006 03:35
PHP Suggests: Some web servers (e.g. Apache) change the working directory of a script when calling the callback function. You can change it back by doing, for example, the following in the callback function: chdir(dirname($_SERVER['SCRIPT_FILENAME']))

The solution provided by PHP, does not function as intended when running PHP as a CGI (on CGI mode (CGI-BUILD (--enable-cgi) and/or CLI)).  In such a case, PHP is executed as a CGI-BIN and the web server daemon (e.g. Apache) sees SCRIPT_FILENAME as being the PHPCGI processor, and won't look deeper to find what file the PHPCGI processor is actually running/parsing; therefore the path returned by SCRIPT_FILENAME is wrong (most of the time, containing/ending with "cgi-system/php.cgi").

As SCRIPT_FILENAME is the safest way to proceed, but turns to be wrong in this exact situation; PATH_TRANSLATED is the next safe solution one would turn towards since it is populated with a different mechanism.

It would be correct to develop in the direction if the script filename itself is contained in the SCRIPT_FILENAME path value, then the SCRIPT_FILENAME content is reported correctly. If it is not, using PATH_TRANSLATED is the next logical choice we can use. The best reference in this case would be PHP_SELF as it is populated by PHP itself. Using SCRIPT_NAME as a reference would be an error as it is affected by the same problem (reports cgi-system and/or php.cgi as well).

The following is the revised code and should work on both the non-CGI and the CGI PHP processor types.

<?php
chdir
(dirname((strstr($_SERVER["SCRIPT_FILENAME"], $_SERVER["PHP_SELF"])
?
$_SERVER["SCRIPT_FILENAME"] : $_SERVER["PATH_TRANSLATED"])));
?>

Or the decomposed code as follows:

<?php
if (strstr($_SERVER["SCRIPT_FILENAME"], $_SERVER["PHP_SELF"])) {
$reference = $_SERVER["SCRIPT_FILENAME"];
} else {
   
$reference = $_SERVER["PATH_TRANSLATED"];
}
chdir(dirname($reference);
?>

This has been tested on Apache 1 & 2, PHP 4 & 5 and IIS 5.1
butch at enterpol dot pl
02-Oct-2006 12:04
simple code to make phpsession $_GET nice for Valid XHTML 1.0 Transitional :)

function callback($buffer)
{
  $buffer = str_replace("&PHPSESSID", "&amp;PHPSESSID", $buffer);
  return $buffer;
}

ob_start("callback");

session_start();
net_navard at yahoo dot com
30-May-2006 07:09
Hello firends

ob_start() opens a buffer in which all output is stored. So every time you do an echo, the output of that is added to the buffer. When the script finishes running, or you call ob_flush(), that stored output is sent to the browser (and gzipped first if you use ob_gzhandler, which means it downloads faster).

The most common reason to use ob_start is as a way to collect data that would otherwise be sent to the browser.

These are two usages of ob_start():

1-Well, you have more control over the output. Trivial example: say you want to show the user an error message, but the script has already sent some HTML to the browser. It'll look ugly, with a half-rendered page and then an error message. Using the output buffering functions, you can simply delete the buffer and sebuffer and send only the error message, which means it looks all nice and neat buffer and send
2-The reason output buffering was invented was to create a seamless transfer, from: php engine -> apache -> operating system -> web user

If you make sure each of those use the same buffer size, the system will use less writes, use less system resources and be able to handle more traffic.

With Regards, Hossein
(capitals) THE maYoR ANd thOSe@gmail
31-Jan-2006 02:14
One of the notes below mentions that ob_end_flush() is called automatically at the end of the script if you called ob_start without an ob_end.

Because I couldn't find any other way to do it, I tried to use this fact to have some stuff run at the end of every script. It was a maintenance nightmare, so I'm putting a link here to the good way to do it, since it's nigh impossible to find with google.

http://php.net/register_shutdown_function
simon
24-Jan-2006 08:51
Found that variables in class instances we're not being set after the call to ob_start().
Call ob_start after the variables are set however and it works but that didn't seem to solve the goal of a self contained templating class.
The fix was to assign the class by reference with '&new'
Here is a simplified working example:
<?php
class Buffer {
var
$template = ' - template set in class constructor';
function
Buffer() {
   
$this->startBuffer();
}
function
startBuffer() {
   
ob_start(array(&$this, 'doFlush'));
}
function
doFlush($buffer) {
   
/* simple string concat to show use of a
    template string and the buffer output */
   
return $buffer . $this->template;
}
}
/* template does not get set:
$buffer1 = new Buffer();
$buffer1->template = ' - template set in instance';
echo 'some buffer content';
*/
/* this works as expected */
$buffer2 = &new Buffer();
$buffer2->template = ' - template set in instance';
echo
'some buffer content';
ernest at vogelsinger dot at
08-Jan-2006 09:57
When you rely on URL rewriting to pass the PHP session ID you should be careful with ob_get_contents(), as this might disable URL rewriting completely.

Example:
ob_start();
session_start();
echo '<a href=".">self link</a>';
$data = ob_get_contents();
ob_end_clean();
echo $data;

In the example above, URL rewriting will never occur. In fact, rewriting would occur if you ended the buffering envelope using ob_end_flush(). It seems to me that rewriting occurs in the very same buffering envelope where the session gets started, not at the final output stage.

If you need a scenario like the one above, using an "inner envelope" will help:

ob_start();
ob_start();   // add the inner buffering envelope
session_start();
echo '<a href=".">self link</a>';
ob_end_flush(); // closing the inner envelope will activate URL rewriting
$data = ob_get_contents();
ob_end_clean();
echo $data;

In case you're interested or believe like me that this is rather a design flaw instead of a feature, please visit bug #35933 (http://bugs.php.net/bug.php?id=35933) and comment on it.
cyrille.berliat[no spam]free.fr
16-Oct-2005 03:07
If you're trying to use ob_start() in some PHP5 classes (probably works on PHP4 classes), this is the good way :

<?

class HTMLPage
{
//----------------------------------------------------------------- PUBLIC

//----------------------------------------------------- M
Новости
11 июля 2007
Сайт запущен
© 2007 info@grandviewstudio.com
Z058440144362 Z348613067571