I don't know why, but this code worked for me a month ago... maybe I upgraded the php but can't remember. Tried this with PHP 5.2.17 and 5.3.6
Why is it not possible to use a class object inside the callback of a ob_start function?
<?php
$f=new stdClass();
$f->title="awesome Title";
function callback($buffer)
{
global $f;
$buffer=str_replace("###TITLE###", $f->title, $buffer);
return $buffer;
}
ob_start("callback");
?>
This is the ###TITLE###
Output is:
PHP Notice: Trying to get property of non-object in /Users/qxxx/Sites/test/test.php on line 8
This is the
should be:
This is the awesome Title
Definition and Usage The ob_start() function creates an output buffer. A callback function can be passed in to do processing on the contents of the buffer before it gets flushed from the buffer. Flags can be used to permit or restrict what the buffer is able to do.
In order to enable the Output Buffering one must use the ob_start() function before any echoing any HTML content in a script.
Using ob_start allows you to keep the content in a server-side buffer until you are ready to display it. This is commonly used to so that pages can send headers 'after' they've 'sent' some content already (ie, deciding to redirect half way through rendering a page).
This is because the output buffer is being implicitly flushed by the termination of the script.
At this point PHP has already destroyed unreferenced variables, so when it comes to execute your callback function, the variable $f
does not exist in the global scope.
You can solve this by explicitly flushing the buffer before shutdown starts destroying objects, by placing the following line somewhere in your script.
register_shutdown_function('ob_end_flush');
Edit:
I'd like to add that even though this is currently the accepted answer that explains the "why", the solution provided here does not address the root cause of the issue; the fact that global
is being used.
Many people will tell you that global
is evil, without giving a reason why. Here you can see one of the reasons.
The answer provided by Jack gives a more "best practice" solution (using closures to maintain the variable reference), and should be considered as the proper way to avoid using global
in new codebases.
The reason for this has been outlined well by Leigh. Using a closure would work better in this case:
ob_start(function($b) use ($f) {
return str_replace('###TITLE###', $f->title, $b);
});
This is because the closure will keep the reference to $f
alive by the end of the script so that it won't get garbage collected before running the callback function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With