有没有办法将 require_once() 的范围显式设置为全局?
Posted
技术标签:
【中文标题】有没有办法将 require_once() 的范围显式设置为全局?【英文标题】:Is there a way to set the scope of require_once() explicitly to global? 【发布时间】:2012-02-16 22:08:14 【问题描述】:当require_once()
在函数内部使用时,我正在寻找一种将require_once()
的范围设置为全局范围的方法。类似下面的代码应该可以工作:
文件`foo.php':
<?php
$foo = 42;
实际代码:
<?php
function includeFooFile()
require_once("foo.php"); // scope of "foo.php" will be the function scope
$foo = 23;
includeFooFile();
echo($foo."\n"); // will print 23, but I want it to print 42.
有没有办法明确设置require_once()
的范围?有什么好的解决方法吗?
【问题讨论】:
require_once
的范围在您定义使用它的位置明确设置。
我能想到一个可怕的解决办法,如果你想要的话......
没有。您需要明确列出要别名到全局范围的变量。在函数中或包含脚本的顶部。
@DaveRandom:也许你应该把它添加为答案^^
为什么要在函数中包装require_once()
?
【参考方案1】:
除了“全球化”你的变量,没有办法做到这一点:
global $foo;
$foo = 42;
或
$GLOBALS['foo'] = 42;
那么当你打印出来的时候你的值应该是 42。
更新
关于包含类或函数,请注意所有函数和类总是被认为是全局的,除非我们谈论的是类方法。此时,类中的方法只能从类定义本身获得,而不是作为全局函数。
【讨论】:
我刚试过你的答案,效果很好。如果文件foo.php
包含函数或类,应该没有问题吧?
谢谢马修。您的解决方案非常适合我的应用程序。【参考方案2】:
根据您的具体要求,您可以使用constants。要求您的文件在全局范围内,但在其中设置一个常量。
IE 文件.php:
define('MY_CONSTANT', 42);
然后在脚本中的任何地方只需使用MY_CONSTANT
来引用该值,但一旦设置,您将无法编辑。除此之外,您可以像其他答案所说的那样全球化您的变量,但是除了简单地从包含的文件中检索一个值之外,您还试图实现什么并不是 100% 清楚?在这种情况下,常量应该没问题。
更新: 现在您已经解释了您希望对象属性在任何地方都可用,我建议您考虑创建一个static class,它一旦在您的全局范围内实例化,就可以在您的应用程序的任何地方使用。阅读链接的手册页,它有一个简单的示例。
【讨论】:
我认为用户希望能够更新现有值,但如果只是外部常量,那么你的方法显然是最好的 在我的应用程序中,$foo
将是一个对象。对象不能存储在常量中,对吧?【参考方案3】:
您需要在foo.php
中声明全局:
<?php
global $foo;
$foo = 42;
?>
否则可能是不可能的。
您可以尝试使用extract()
、get_defined_vars()
、global
和$GLOBALS
进行各种组合...就像遍历所有已定义的变量并在需要文件之前对它们调用全局...
$vars = get_defined_vars();
foreach($vars as $varname => $value)
global $$varname; //$$ is no mistake here
require...
但我不太确定你是否到达了你想去的地方......
【讨论】:
啊顺便说一句...我有没有提到这有点可怕,这里的所有内容都只能用作错误的示例如何不做事...对于您的基本问题可能有一个非常好的解决方案正在尝试解决,而不会严重滥用全局命名空间;)【参考方案4】:由于在您使用 require
等的地方明确定义了范围,您需要指定如何处理函数范围内的变量:
function includeFooFile()
require_once("foo.php"); // scope of "foo.php" will be the function scope
foreach (get_defined_vars() as $k => $v)
$GLOBALS[$k] = &$v;
此示例同时处理变量和引用,这可能是您正在寻找的。 Demo。请注意,require_once
只会工作一次,并且只会定义一次变量。
【讨论】:
【参考方案5】:这绝对是不是一个“不错”的解决方法,但它会起作用:
function includeFooFile()
require_once("foo.php");
foreach (get_defined_vars() as $key => $value)
// Ignore superglobals
if (!in_array($key, array('GLOBALS','_SERVER','_GET','_POST','_FILES','_COOKIE','_SESSION','_REQUEST','_ENV')))
$GLOBALS[$key] = $value;
但是,您包含的文件不能定义任何函数或类(可能还有一些我目前无法想到的其他内容),因为它会导致解析错误,因为您不能嵌套类或函数。
EDIT 显然您可以在文件中包含函数。我一直认为你不能,但经过测试,你似乎可以。
【讨论】:
这似乎是解决我的问题的一种解决方法。我现在要试试... @DaveRandom:这不支持别名,超全局变量已经被覆盖,所以理论上不需要检查。实际上,get_defined_vars()
无论如何都不会在本地函数范围内返回它们。
@hakre 确实在正确测试后(5.2.17/win32)它没有,当我为了这个答案的目的检查它时,我在全局范围内做了它,它们被返回。我不明白为什么它们不会出现 - 根据定义,超全局变量是在 every 范围内定义的。我将保留此答案,以防此行为在未来版本中发生变化。我宁愿检查而不是覆盖超全局变量,以防万一发生我没有预见到的事情(尤其是$GLOBALS
)——正如你所说,它们已经被覆盖了,所以它应该几乎没有什么实际区别。
@hakre 你是对的(第一次也认为get_defined_vars()
将返回当前范围内的 all 可访问变量)。在 PHP 5.3.3 中它只返回函数范围内的变量...
如果文件不能定义函数,它几乎是没用的——因为这就是你通常包含它们的原因【参考方案6】:
我还没有尝试过(因为使用全局变量是个坏主意)但这可能会起作用:
require_once '...';
$GLOBALS = array_merge($GLOBALS, get_defined_vars());
您也可以手动操作:
foreach (get_defined_vars() as $k => $v)
$GLOBALS[$k] = $v;
【讨论】:
为什么你认为使用全局变量是个坏主意? 这是一个教条 :) 你可以用谷歌搜索它,有足够多的解释,最适合任何语言。基本上,即使您需要全局访问数据,也请将其放在不会干扰其他内容的地方。在 PHP 中,静态类变量是一个不错的选择(恕我直言)。【参考方案7】:你可以使用我写的这个hacky函数:
/**
* Extracts all global variables as references and includes the file.
* Useful for including legacy plugins.
*
* @param string $__filename__ File to include
* @param array $__vars__ Extra variables to extract into local scope
* @throws Exception
* @return void
*/
function GlobalInclude($__filename__, &$__vars__ = null)
if(!is_file($__filename__)) throw new Exception('File ' . $__filename__ . ' does not exist');
extract($GLOBALS, EXTR_REFS | EXTR_SKIP);
if($__vars__ !== null) extract($__vars__, EXTR_REFS);
unset($__vars__);
include $__filename__;
unset($__filename__);
foreach(array_diff_key(get_defined_vars(), $GLOBALS) as $key => $val)
$GLOBALS[$key] = $val;
当包含文件返回时,它将任何新定义的变量移回全局空间。需要注意的是,如果包含的文件包含另一个文件,它将无法通过 $GLOBALS
访问父文件中定义的任何变量,因为它们还没有被全球化。
【讨论】:
以上是关于有没有办法将 require_once() 的范围显式设置为全局?的主要内容,如果未能解决你的问题,请参考以下文章