我不知道为什么,但这个代码一个月前对我有用......也许我升级了php但不记得了。尝试使用PHP 5.2.17和5.3.6
为什么不能在ob_start函数的回调中使用类对象?
<?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###
输出是:
PHP Notice: Trying to get property of non-object in /Users/qxxx/Sites/test/test.php on line 8
This is the
应该是:
这是很棒的标题
答案 0 :(得分:10)
这是因为脚本终止会隐式刷新输出缓冲区。
此时PHP已经销毁了未引用的变量,因此在执行回调函数时,全局范围内不存在变量$f
。
您可以通过在关闭开始销毁对象之前显式刷新缓冲区来解决此问题,方法是将以下行放在脚本中的某处。
register_shutdown_function('ob_end_flush');
修改强>
我想补充一点,尽管这是目前接受的解释“why”的答案,但此处提供的解决方案并未解决问题的根本原因; global
正在使用的事实。
很多人会告诉你global
是邪恶的,没有给出理由。在这里你可以看到其中一个原因。
杰克提供的答案提供了更多“最佳实践”解决方案(使用闭包来维护变量引用),应该被视为避免使用global
的正确方法新的代码库。
答案 1 :(得分:6)
Leigh概述了这个原因。在这种情况下,使用闭包会更好:
ob_start(function($b) use ($f) {
return str_replace('###TITLE###', $f->title, $b);
});
这是因为闭包将在脚本结束时保持对$f
的引用活动,以便在运行回调函数之前不会收集垃圾。
答案 2 :(得分:2)
从ob_start
的php手册页和a bug report我了解到,自5.2以来,所有对象都被销毁了@ob_start
此功能的行为已在php 5.2.0中更改:
<?
global $AP;
$AP = new ap;
ob_start("ob_end");
function ob_end()
{
global $AP;
$r = $AP->test();
return $r;
}
class ap
{
function test()
{
return "debug";
}
}
?>
在旧版本中显示:“debug”。 但是最新的php版本会导致错误:PHP致命错误:调用&gt;上的成员函数test()一个非对象。 这不是一个错误:http://bugs.php.net/bug.php?id=40104
来自手册页