更新:我显然把这个问题简单化了,并且有几个人对这个问题的愚蠢性发表了正确的评论。但是,仍然存在$GLOBALS
未按预期运行的情况,我将在下一篇文章中概述这些情况。
在我之前的条目中,我大肆宣扬了在流行的PHP应用程序中使用全局变量,以及它们如何使嵌入上述应用程序变得困难。我使用面向对象的实践进行开发,并且可以诚实地说我不记得曾经在我自己的代码中使用过全局变量。全局变量对我来说似乎很老套,因此,试图让使用它们的应用程序正确运行一直是一个挑战。
我想到的其中一个应用程序是Serendipity,它是为这个博客提供支持的软件。我试图创建一个ZendFramework动作控制器来包装我的s9y实例,这样我就可以做一些事情,比如将ACL从我的网站应用到选定的条目,以及从s9y中拉出整个站点的框架,这样我只需要维护它的一个版本(我有一个版本用于s9y,另一个版本用于网站上我自己的内容(简历、联系表等)。
在调用实际的s9y引导程序之前,我尝试将各种配置文件导入到我的操作方法中,但没有成功。我还尝试修改s9yconfig文件以在这些意外配置变量周围使用符号$GLOBALS['serendipity']
(s9y对所有配置选项使用单个多维数组)。这也不管用;调用全局$serendipity
的s9y函数仍然得到空值。
所以,我仔细阅读了有关预定义变量的手册部分,我在$GLOBALS
的描述中发现了一些有趣的东西(强调我的):
包含对脚本全局范围内当前可用的每个变量的引用。
包含对脚本全局范围内当前可用的每个变量的引用。
有趣的是,关于变量作用域的部分根本没有做出这种区分。基本上,如果您通过$GLOBALS
引用的变量不存在,分配它什么都不做。它甚至没有发出通知。它只是默默地进行,让你以为你设置了一个新的全局变量,但实际上,你不能通过$GLOBALS
分配新的全局变量;您只能在全局范围内修改现有变量。
所以,我通过将它放在我的前端控制器引导程序中解决了这个问题:
$serendipity = null;
在那之后,我能够非常轻松地为s9y创建一个包装器动作控制器:
/** Zend_Controller_Action */ require_once 'Zend/Controller/Action.php'; /** * Serendipity integration * * @uses Zend_Controller_Action */ class S9y_IndexController extends Zend_Controller_Action { public function init() { // New ViewRenderer helper in ZF incubator; telling it not // to autorender a view script when done $this->_helper->viewRenderer->initView(null, null, array('noRender' => true)); } public function indexAction() { global $serendipity; chdir($_SERVER['DOCUMENT_ROOT'] . '/path/to/s9y'); include './index.php'; chdir($_SERVER['DOCUMENT_ROOT']); } }
请注意,我没有做任何输出缓冲;这是因为ZF调度员为我处理了这件事。我需要做的就是执行s9y引导程序。
因此,从这一切中吸取的教训是:如果您需要包装一个使用全局变量的应用程序,找出它们的全部内容,并在您的应用程序引导程序中在全局命名空间中声明它们——只需将它们设置为null就足够了。