20

So I have a function such as:

public static function UnorderedList($items, $field, $view = false){
    if(count($items) > 0){
        echo '<ul>';
        foreach($items as $item){
            echo '<li>';
            if($view){
                echo '<a href="'.$view.'id='.$item->sys_id.'" title="View Item">'.$item->$field.'</a>';
            }else{
                echo $item->$field;
            }   
            echo '</li>';
        }
        echo '</ul>'; 
    }else{
        echo '<p>No Items...</p>';
    }
}

This function loops over some items and renders a unordered list. What I am wondering is if its possible to capture the echo output if I wish.

I make a call to use this function by doing something like:

Render::UnorderedList(Class::getItems(), Class::getFields(), true); 

And this will dump a unordered list onto my page. I Know I can just change echo to a variable and return the variable but I was just curious if its possible to capture echo output without modifying that function, merely modifying the call to the function in some way?

Thanks!

Chris
  • 11,780
  • 13
  • 48
  • 70

2 Answers2

57

Yes, using output buffering.

<?php
ob_start(); // Start output buffering

Render::UnorderedList(Class::getItems(), Class::getFields(), true); 

$list = ob_get_contents(); // Store buffer in variable

ob_end_clean(); // End buffering and clean up

echo $list; // will contain the contents
 ?>
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • @Pekka: In terms of design for a small MVC framework specific to a project of mine would this be a good way to go? I have an application that relies on a soap web service for its data and this is a Render class which accepts objects by argument and renders HTML based on them as you saw with this unorderedlist function. Just curious what your thoughts are on this. Based on that solution I can see pages like index.php having a lot of ob_start, ob_end_cleans with function calls in between. Perhaps I learned something new but still need to rework the static library of rendering functions ? – Chris Oct 12 '10 at 18:09
  • @Pekka: perhaps I could have Render class's functions all have ob_start(), ob_get_contents(), ob_end_clean() in them and have a public field for this class which is appended the result of ob_get_contents? This way I could build the page up using the Render class and at the very end do a simple echo Render::$contentsfield; ? – Chris Oct 12 '10 at 18:14
  • @Chris Mmm, using output buffering as part of a library doesn't sound like good practice to me. This is more the kind of thing you do when you *have* to, e.g. when working with an external library that echoes stuff. Why not change the behaviour of the class methods to return the data instead of echoing it, and make the page itself (the one calling the Render class) echo the results? – Pekka Oct 12 '10 at 18:24
  • Fair enough, based on from what I have seen of you around SE I will take your advice whole heartedly. :-) Cheers mate. – Chris Oct 12 '10 at 18:31
5

Very Similar to previous answer but a little more concise for my purposes:

<?php
ob_start(); // Start output buffering

Render::UnorderedList(Class::getItems(), Class::getFields(), true); 

$list = ob_get_clean(); // Store buffer AND cleans it

echo $list; // will contain the contents
?>

I also want to mention how useful this is for PHP unit testing so as not to clutter your test logs with the output of what you are testing unless the test fails. Here is another stackflow answer related to this because I found this answer first on my google search when I was looking at how to test items with echo output : How to use output buffering inside PHPUnit test?

Kevin_Ankiewicz
  • 131
  • 2
  • 4