ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

Flushing with code ignitor?

April 04, 2009 11:43am

Subscribe [9]
  • #1 / Apr 04, 2009 11:43am

    Pheet

    1 posts

    Hi,

    I’m wondering how to implement flushing of content with code ignitor.

    In previous (non CI) work I’ve done something along the lines of:

    ob_start("ob_gzhandler");
    include 'header.inc.php';
    @ob_flush();
    flush();
    // do some work
    include 'footer.inc.php';

    In addition to the improved page loading time, it’s some time useful when doing long tasks (sending email, complicated DB queries etc.) to:
    * output head content
    * display a busy image
    * flush
    * do the the task
    * output “task complete” with a bit of javascript that hides the busy image.

    Within CI simply trying ob_flush() etc after loading a view simply doesn’t work, as CI is using (multiple ?) output buffers behind the scenes (to deal with nested views IINM).

    I can do a nasty hack of loading the header view, echoing the output buffer, flushing, emptying the output buffer, then load the main view etc., but:
    * This is nasty
    * It breaks as soon as output compression is enabled in the config.

    Anyone got ideas where I start? I imagine I need to extend the output class and/or write some hooks, but at the moment I’m not sure where to start.

    TIA,
    Pheet

  • #2 / Nov 24, 2009 5:56pm

    billapepper

    1 posts

    I was having the same problem… I want the header of my site to load before the “content” has been processed… as this may take 2-3 seconds… I have the header as it’s own view… eg.

    $this->load->view('includes/header');
        $this->load->view($content);
        $this->load->view('includes/footer');

    Where $content will be the name of the view that determines the content…

    Even with seperate views, and adding tons of ob_start(), ob_flush(), flush(), etc. in a bunch of different places in the code, nothing shows until the entire content of all called views have been processed…

    This makes it so when you click a link on one page, nothing happens for 2-3 seconds, then the new page loads all at once…

    I need the header to load immediately, followed a few seconds later by the rest of the content… this way, people will know they actually clicked a link, and they can use the site navigation while waiting if they wanted to go to a different site.

    I’ve searched the forums and can’t figure out a proper way to flush to buffer… is it possible? We’re in the R&D stage, and if this can’t be done we’re going to have to rethink the architecture of our site completely.

  • #3 / Dec 02, 2009 6:57pm

    summery

    26 posts

    Hola.  I’d also like to be able to flush the output buffers early, but the forums and google seem to be mysteriously silent.  If you have an implementation, please post it!  Thanks, ~S

  • #4 / Dec 02, 2009 11:01pm

    InsiteFX

    6819 posts

    Try placing the ob_start(); at the top of your controller.

    Enjoy
    InsiteFX

  • #5 / Apr 22, 2010 11:20am

    billmce

    56 posts

    That worked for my problem!
    thanks.

  • #6 / Oct 21, 2010 3:26pm

    Nekluh

    8 posts

    Have this stopped working, or am I doing it wrong?

    I begin with
    ob_start();

    then making this every loop:
    ob_flush();
    flush();

    But everything renders at the same time anyway

  • #7 / Oct 21, 2010 5:14pm

    WanWizard

    4475 posts

    In CI all output goes through the Output class, which buffers all output. If you use ob_start(), you’ll just add another level of buffering, and flush() will actually flush into the buffer managed by the Output class.

    Also, output is buffered when you have compression enabled. If you have this enabled in the PHP config, the output is even buffered without using ob_start() or the output class… You can test that by echo’ing some text out in a loop, with a delay between the echo’s. CI doesn’t buffer echo’s, so if the output still appears all at once, output is being buffered elsewhere.

  • #8 / Oct 22, 2010 4:52am

    Nekluh

    8 posts

    Ok thanks.

    It started working as I skipped ob_start()

  • #9 / Feb 01, 2012 12:42am

    Tybion

    9 posts

    The above did not work for me with CI 2.1.0, exactly, but this did ..

    First thing in the Controller method, call ob_start() ..

    public function report($page) {
        ob_start();   // create a top output buffer

    In the View file, the following gets the content to the browser ..

    //Once I have 200 rows to display, give the user something to look at, while waiting for the rest ..
      if ($count==200) {
        ob_end_flush(); // php.net:'send the contents of the topmost output buffer and turn this output buffer off'
        ob_flush();     // for an unknown reason, need another flush
      }

    If you understand why this works, can you please add an explanation to this article.

     

  • #10 / Feb 01, 2012 4:43pm

    Tybion

    9 posts

    Another way that works in CI 2.1.0 is to do as above in the controller, and then near the top of the View have only these 2 lines ..

    ob_end_flush();  // flush and turn off my outer output buffer
    ob_end_flush();  // turns off the inner CI output buffer?

    Yet another way in the View (using the same controller) is ..

    ob_end_flush();  // flush and turn off my outer output buffer
    //   :    :
    // in a loop flush the inner CI buffer every 200 rows
      if ($count % 200 == 0) {
        ob_flush();
      }

     

  • #11 / Feb 01, 2012 7:06pm

    CroNiX

    4713 posts

    echo $this->load->view('view_file', $data, TRUE);

    Will bypass buffering entirely, as WanWizard eluded to.  If the 3rd parameter is set to TRUE, it returns the view instead of buffering it for final output, so you can directly echo it out or assign it to another variable that gets passed to a template or whatever.

  • #12 / Feb 01, 2012 8:10pm

    Tybion

    9 posts

    Thanks, CroNiX, for your help.

    Unfortunately, this does not work for me in CI 2.1.0.  The following code creates the page CONTENT exactly as it should, but it does not get updated in the browser until the whole page has arrived (about 8 seconds).

    (Also, in my rpt_table.php view, all of the table creation - 6,000 rows - is done with echo statements, but using the echo statements does not prevent the output being buffered.)

    public function report($page) {                         // routes.php: $route['warehouse/(:any)']='warehouse/view/$1'
        if ($page=='drillhole') {
          $object=$this->drillhole_model;
        } else {
          die("
    No report available for $page
    ");
        }
        $data=$object->get_params();           // set minx, base_url, etc. in session variables
        $data['query'] = $object->get_data($data);    // query object
        $data['title'] = 'Data Warehouse';
        echo $this->load->view('templates/rpt_header', $data, TRUE);       // views/templates/rpt_header.php
        echo $this->load->view('warehouse/rpt_table', $data, TRUE);       // views/warehouse/rpt_table.php - TRUE=return data instead of writing to browser.
      }
.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases