Jump to content

output buffering


frijole

Recommended Posts

I am working on a member system for my site and in some tutorials I have come across the function ob_start(). I have looked in the manual and I am still confused as to its function. Here is an example of its use in context:

 

<?
ob_start();
require_once($_SERVER['DOCUMENT_ROOT'].'/db_connect.php'); 

if(isset($_SESSION['username']) && isset($_SESSION['password'])) {
       //REDIRECT TO USERS PROFILE...
   header("Location: http://www.your_site.com");
} //end if logged in


//IF SUBMIT BUTTON PRESSED
if(isset($_POST['submit'])) {

   if(!$_POST['username']) die("Error: You must enter your username before logging in.");
   if(!$_POST['password']) die("Error: You must enter your password before logging in.");
   
//set cookie if checked
   if(!empty($_POST['stay_in'])) {  
         $joined =''.$_POST['username'].'[]'.md5($_POST['password']).'';
         setcookie('login_cookie', $joined, 2147483647, '/', '.www.yoursite.com');   
    } //end if

//verify user...
$get_user = mysql_query("SELECT * FROM `members` WHERE username = '".$_POST['username']."' AND 

user_password = '".md5($_POST['password'])."'");
$q = mysql_fetch_object($get_user);
    if(!$q) die("Login Failure: An error occured, please verify your username and password are correct.");

//set session variables 
$_SESSION['logged_in'] = 1;
$_SESSION['username'] = $_POST['username']; 
$_SESSION['password'] = $_POST['password']; 
session_write_close();

header("Location: http://www.yoursite.com");

} else {
//show login form
?>
<form name="login" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
<table>
<tr>
  <td>Username:<input type="text" id="username" name="username"></td>
</tr>
<tr>
  <td>Password:<input type="password" id="password" name="password"></td>
</tr>
<tr>
  <td>Submit: <input type="submit" value="Submit" name="submit" id="submit"></td>
</tr>
<tr>
<td>Remember? <input type="checkbox" name="stay_in[]" checked="yes"></td>
</tr>
</table>
</form>
<?
}//end else
?>

 

What does it do, and why is it important?

Link to comment
Share on other sites

ob_*** (or outbut buffering) functions should be left well alone unless you're using it for its correct purpose. i see so many people using it to handle 'header' errors, when just a bit of organising of code and a little more understanding of exactly how PHP is actually processing your page is much better.

 

in its proper use, ob_start will start output buffering - that is to say that anything you 'echo' will not be output to the screen, but will be placed inside of a buffer. this buffer can then be manipulated or emptied or just about whatever you want, and when you want to, you just dump the contents to the screen. common uses would be for 'templating' or manipulation of an entire page just before outputting it.

 

in its 'hacky' use - when you have output something to the screen but then send a 'header' (for example, to redirect the page), PHP will generate an error along the lines of 'headers already sent' and the page will not redirect. however, starting output buffering first (with ob_start()) means that anything output (including these errors) that would cause the page to not redirect, is stored in the buffer instead (and emptied to the screen at the end of your script).

 

a better practice to avoid the hacky method is to do ALL checks/processing that may end up in a redirect (ie, with header("Location: /someurl") ) before you send ANY output (be it via an echo, or actul HTML). also, following the header line with a call to exit() is common practice. so in your case - lose the ob_start line altogether (never let ANYONE tell you this is good practice or the right thing to do in 2008) and add exit() to the line after the header. so:

 

header("Location: http://www.your_site.com");
exit;

.. rest of code here...

Link to comment
Share on other sites

Echo Mark.

 

Output buffering makes sense, in fact a while ago I even came across some benchmarks saying it would generally improve performance. But a more general use would be to encode the output, for example using gzip.

 

In the past I've also made myself guilty of using output buffering to correct headers being sent by some messy 3rd party software, Drupal in that case. Not advisable in general.

Link to comment
Share on other sites

Output buffering is perfectly valid, for the purpose of buffering output :-)

 

Output buffering allocates a larger memory size than a php string, so sending large output to it instead of a variable is more efficient due to less resizing behind the scenes.

 

Sending all output at one time, without delay allows for less packets to be sent which aids communications. As stated, turning on gzip handler for your output buffering will also reduce the amount of data sent.

 

Don't let anyone in 2008 tell you output buffering is evil :-)

Link to comment
Share on other sites

@able - just to clarify, nobody as yet here has said output buffering is evil - just that using it to "smooth over" errors that should not be produced in the first place is bad. If you look at some of the code where they tell you to "throw ob_start at the top", the sheer spaghettiness (!) of the code clearly points out that they're not using output buffering to take advantage of it's more useful benefits - more just hacking something dirty together as quickly as possible. in many a tutorial where you see an 'ob_start()' right at the top of the code, you'll also see heavy use of the "shut-up" operator (@).

 

my advice if you're just starting out (and hence possibly not ready for stuff like MVC, etc to structure things nicely) is to put ALL your logic in a block at the very top of your PHP file. This logic should NOT have a single echo or any raw HTML. This block will deal with form input checks, mysql stuff, redirection, etc. Anything you want to display at this point, store it in a variable. After you've closed this PHP block with your good old ?> tag, then comes the HTML. If you're using PHP after this point, it really should only be concerned with stuff regarding the display.

 

for example:

 

<?php
   if ($_GET['test'] == 'redirect') {
      header("Location: /somewhereelse.php");
      exit;
   }
   else {
      $title = 'Hello World';
      $body = 'Lorem Ipsum etc etc etc etc....';
      $extrabody = 'This is a test';
   }
?>
<html>
...
<body>
   <h1><?php echo $title ?></h1>
   <p><?php echo nl2br($body) ?></p>

   <?php if ($extrabody): ?>
      <p><?php echo nl2br($extrabody) ?></p>
   <?php endif ?>
</body>
...
</html>

 

apologies for the non-ob_start related lesson, but hopefully it'll help you sort out your code structures in future so that hacks are not required to handle errors and stuff. ob_*** will come in useful in the future when you start getting into seperating out your PHP files from your HTML templates - ie, templating.

 

Hope that helps

Cheers

Link to comment
Share on other sites

in many a tutorial where you see an 'ob_start()' right at the top of the code, you'll also see heavy use of the "shut-up" operator (@).

 

Take look at templates in MediaWiki. They actually turn off reporting of notices, so that can freely request non-existent variables and indices. Now THAT is really crappy.

Link to comment
Share on other sites

Output buffering shines the most when you need to capture data that CANNOT be captured any other way.

I.E. Caching rendered HTML:

 

<?php

function recent_comments() {

    //If a catched copy does NOT already exist
    if(!cache_exists('recent_comments')) {
    
        //Start by cache-ing everything so that PHP doesn't just print the recent_comments to the screen.
        ob_start();
        
        
        //Here you would query the database for the last 10 comments
        ...
        //Then you would place them in the HTML set by the current them
        ...
        
        
        //When you were done placing the last 10 in an <UL> or whatever
        //you could store the complete list in a string and save it as
        //a catch.
        
        
        //Stick the cache contents into the variable...
        $output = ob_get_contents();
        
        //Then kill the cache...
        ob_end_clean(); 
    
    
        //Make a catched version
        create_cache($output);
    
    
    //Else we already made a catched version of the resent comments
    } else {
        //So just print it out
        print get_cache('recent_comments');
    }
}
?>

Link to comment
Share on other sites

I've used it a couple of times to avoid modifying third party software. I'm always weary of that as it can break upgrade paths. So in the past I've captured the HTML that the third party software rendered, then ran a regular expression over it to remove stuff, modify the display, etc.

Link to comment
Share on other sites

Think about it, each print/echo requires a new socket open to send data - by buffering it all you can send everything in one shot.

 

It does speed up comunications, but it's nothing to do with the number of sockets. Sending multiple echo's without output buffering does not use multiple sockets.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.