0

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.

hakre
  • 193,403
  • 52
  • 435
  • 836
intacto
  • 451
  • 4
  • 12

2 Answers2

0

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";
Kris
  • 40,604
  • 9
  • 72
  • 101
  • Hi, I've edited my question. I just made some errors while simplfying the code. The error still exists. Please check the updated example. – intacto Nov 16 '12 at 11:59
  • I wrote this in textmate and tested it. works fine as per your original question, outputting "helloworld" with php 5.3.16. – Kris Nov 16 '12 at 12:01
  • Tested it on both local apache server with php 5.4.3 and remote lighttpd server with php 5.3.18. They both output just "hello". Please check the updated example code. – intacto Nov 16 '12 at 12:07
  • Your updated example code references an object that has been destroyed by the looks of things. – Kris Nov 16 '12 at 12:16
  • Why is $anotherClass destroyed and how could I prevent it to be destroyed before callback function? – intacto Nov 16 '12 at 12:25
0

The problem occurs because objects without references are destructed before the output_callback is executed. So you can fix the problem by adding a reference to the object you want to save.

Fixed example:

<?php
class AnotherClass{
    public $world = "world";
}

$anotherClass = new AnotherClass();

class TestClass{
    private $globals;

    function __construct(){
        global $anotherClass;
        $this->globals[]=&$anotherClass;
        ob_start(array($this,"callback"));
    }

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

$tClass = new TestClass();

echo "hello";
?>
intacto
  • 451
  • 4
  • 12