The downside of Output Buffers
Moderator: General Moderators
- evilmonkey
- Forum Regular
- Posts: 823
- Joined: Sun Oct 06, 2002 1:24 pm
- Location: Toronto, Canada
The downside of Output Buffers
Hello,
I use output buffers (ob_start/ob_end_flush) to do various things on my website. For one thing, I am sometimes forced to use the header() function to redirect users to other pages (error pages and the like). I have headers, footers, (I use include_once), and I also use the smarty templating system. I use output buffers to suppress the "headers already sent" errors when I need to redirect. My question is, is there a downside to doing this? (unexpected behaviour, slow-downs, etc.)
Thanks.
I use output buffers (ob_start/ob_end_flush) to do various things on my website. For one thing, I am sometimes forced to use the header() function to redirect users to other pages (error pages and the like). I have headers, footers, (I use include_once), and I also use the smarty templating system. I use output buffers to suppress the "headers already sent" errors when I need to redirect. My question is, is there a downside to doing this? (unexpected behaviour, slow-downs, etc.)
Thanks.
- Buddha443556
- Forum Regular
- Posts: 873
- Joined: Fri Mar 19, 2004 1:51 pm
- evilmonkey
- Forum Regular
- Posts: 823
- Joined: Sun Oct 06, 2002 1:24 pm
- Location: Toronto, Canada
No, but the user is only redirected if (for example) he is not logged in...or if there's an input error. If everything is fine, then a page is displayed.Buddha443556 wrote:On a redirect, that would be needlessly as output buffer is allocated 40KB. Including headers, footers and smarty is probably more costly though for just a redirect.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
A better way to deal with this is to have a Response object that handles the final HTTP output and frees you code to focus on building and setting things. In it simplest form it is:
I usually make this object available, along with a Request object, available via a Registry/Service Locator of some sort. The program adds content and/or sets headers as needed. At the very end of the main script you do a $response->out() and it sorts out what needs to be sent. It allows you code to be kept very modular, because the rendering parts can just do their job, but if there is some sort of error or access problem then just set the redirect and bail out.
Example usage:
Code: Select all
class Response {
var $_headers = array();
var $_content = '';
function setRedirect($location) {
$this->addHeader("Location: $location");
}
function addHeader($string, $replace=true) {
$this->_headers[$string] = $replace;
}
function addContent($content) {
$this->_content .= $content;
}
function out() {
if ($this->_headers) {
foreach ($this->_headers as $string => $replace) {
header($string, $replace);
}
} else {
echo $this->_content;
}
}
}Example usage:
Code: Select all
$response = new Response();
$response->addContent('Hello World!');
$response->setRedirect('other_page.php');
$response->out();(#10850)
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
Came across this idea before and have been using it ever since in my own mini framework. Works very well - a lot better than having echo's and header() calls all over the place... Since its all in one object, it's easy to add in other possible manipulations like gzipping the output, or doing some post-processing.
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
- Buddha443556
- Forum Regular
- Posts: 873
- Joined: Fri Mar 19, 2004 1:51 pm
That Response object is pretty neat.
Obviously we do things differently. If my user isn't logged in then the page controller simple includes a different handler - no redirect. Input error, still no redirect, just an error message along with <FORM> in question. I actually try to avoid redirects because I don't want to load DB, sessions, templates and whatever unless they're needed.No, but the user is only redirected if (for example) he is not logged in...or if there's an input error. If everything is fine, then a page is displayed.
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
I use Output buffering for templating.... I do redirects etc in the controller before I load the template if I need to:
(Maybe my idea of what a "controller" should do is wrong)
(Maybe my idea of what a "controller" should do is wrong)
Code: Select all
<?php
require_once('config.class.php');
require_once('includes/core_components.inc.php');
//The controller is part of
// a larger collection of objects including the
// core, database and config parts of the app
class controller extends myTpl
{
var $moduleName = 'module_name'; /* Can be boolean false */
function controller($tpl='some.tpl.php')
{
//Initilializes the objects below us
$this->start();
//You can leave the module name empty if the user is
// only required to be logged in
// This is where any redirect logic would be. In fact, the authorize()
// call sometimes forces a redirect or a "denied" template to be used
$this->login->authorize($this->moduleName); /* Optional */
//Load the template for this module
parent::myTpl($this->conf->rootPath.'/templates/'.$this->conf->template.'/'.$tpl);
}
function show()
{
/*
Modify $this->tplVars here.
Example:
$this->tplVars['FOO'] = 'Bar';
*/
$source = $this->render();
$source = $this->addHeaders($source, array(
'PAGE1' => $this->moduleName,
'PAGE2' => $this->moduleName,
'WINDOW TITLE' => $this->conf->appTitle
/* 'NAV' => '' //This will remove the navigation bar from overall_header.tpl.php */
));
$source = $this->addFooters($source);
return $source;
}
}
$con =& new controller;
echo $con->show();
?>- Ambush Commander
- DevNet Master
- Posts: 3698
- Joined: Mon Oct 25, 2004 9:29 pm
- Location: New Jersey, US
- evilmonkey
- Forum Regular
- Posts: 823
- Joined: Sun Oct 06, 2002 1:24 pm
- Location: Toronto, Canada
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Actually you almost exactly describe what I do as well. I really only redirect after forms are accepted to deal with back button issues. I forward (dispatch) errors rather than redirecting. So errors are really not that good of an example.Buddha443556 wrote:Obviously we do things differently. If my user isn't logged in then the page controller simple includes a different handler - no redirect. Input error, still no redirect, just an error message along with <FORM> in question. I actually try to avoid redirects because I don't want to load DB, sessions, templates and whatever unless they're needed.
I really use a Response object to ease page building. The one I use also allows any child to add Scripts, Stylesheets, Meta tags, etc. That's probably the main reason for me -- any widget can add a stylesheet or some Javascript without needing to know anything about the detail of page building -- and it just works.
(#10850)
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
They really do two different things. Output buffering captures the output that would normally be sent to the screen so it can be dealt with like an string. The Response object uncouples the specifics of page building from your code. So you may capture an include() in an outbuffer that contains part of the content area of a page -- give it to the Respose object along with some Javascript that that content needs. The Response object puts it all together with the JS in the header and the content in the body.onion2k wrote:What's the difference between using PHP's output buffer and that response object? I can't see any. Seems to just be reinventing something thats already built in.
I should note also that having heirarchical Views further simplfies this process -- the Response object renders a tree of View objects. It may seem like overkill for simple pages, but it really adds flexiblity to not have page-building spaghetti code on every page in larger projects. I find that hierarchical page building saves time in the long run over the traditional header/content/footer sequential page building.
(#10850)