Search code examples
phpoutput-buffering

ob_start output_callback can not access global variables


I'm currently using output buffering for some sort of header & footer automatization. But I need to access global variables inside the output_callback function. If I don't use class oriented code there isn't any issue. But if I try something like:

class AnotherClass{
    public $world = "world";
}

$anotherClass = new AnotherClass();

class TestClass{
    function __construct(){
        ob_start(array($this,"callback"));
    }

    function callback($input){
        global $anotherClass;
        return $input.$anotherClass->world;
    }
}

$tClass = new TestClass();

echo "hello";

While the expected output is helloworld it just outputs hello I would really appreciate it if you could provide some sort of fix which lets me access global variables inside the callback function without first setting them as class variables inside the constructor.


Solution

  • You have an error in your ob_start. the callback should look like: array($this, 'callback') like so:

    <?php
    
    $x="world";
    
    class testClass{
        function __construct(){
            ob_start(array($this,"callback"));
        }
    
        function callback($input){
            global $x;
            return $input.$x;
        }
    }
    
    $tClass = new testClass();
    
    echo "hello";
    

    Additional after changes to question:

    php's output buffering is a bit odd, it seems to be on another piece of stack or something. You can work around this problem by taking a new reference to the variable directly into a closure:

    <?php
    
    class AnotherClass{
        public $world = "world";
        public function __destruct()
        {
            // this would display in between "hello" and "world"
            // echo "\n".'destroying ' . get_called_class() . "\n";
        }
    }
    
    class TestClass
    {
        function __construct()
        {
            global $anotherClass;
    
            // taking a new reference into the Closure
            $myReference = $anotherClass;
            ob_start(function($input) use (&$myReference) {
                return $input . $myReference->world;
            });
        }
    }
    
    // the order here is important
    $anotherClass = new AnotherClass();
    $tClass = new TestClass();
    
    echo "hello";