当函数内部使用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()
范围的方法?有没有一个好的变通办法?
除了"全球化"变量之外,没有办法做到这一点:
global $foo;
$foo = 42;
或
$GLOBALS['foo'] = 42;
那么当你打印出来的时候,你的值应该是42。
更新
关于类或函数的包含,请注意,除非我们谈论的是类方法,否则所有函数和类都被认为是全局的。此时,类中的方法只能从类定义本身获得,而不能作为全局函数。
您需要在foo.php
:中声明全局
<?php
global $foo;
$foo = 42;
?>
否则,这可能是不可能的。
你可以试着用extract()
、get_defined_vars()
、global
和$GLOBALS
进行各种组合,也许。。。比如遍历所有定义的变量,并在需要文件之前对其调用global。。。
$vars = get_defined_vars();
foreach($vars as $varname => $value)
{
global $$varname; //$$ is no mistake here
}
require...
但我不太确定你是否到达了你想去的地方。。。
这绝对不是一个"不错"的解决方案,但它会起作用:
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显然您可以在文件中包含函数。我一直认为你做不到,但经过测试,似乎你可以。
由于范围是在使用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;
}
}
这个例子同时处理了变量和引用,它们可能是您要查找的。演示。请注意,require_once
只工作一次,并且只定义变量一次。
你可以使用我写的这个技巧函数:
/**
* 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;
}
}
当include文件返回时,它会将任何新定义的变量移回全局空间。需要注意的是,如果包含的文件包括另一个文件,它将无法通过$GLOBALS
访问父文件中定义的任何变量,因为这些变量尚未全球化。
我还没有尝试过(因为使用全局变量是个坏主意,tbh),但这可能会奏效:
require_once '...';
$GLOBALS = array_merge($GLOBALS, get_defined_vars());
或者你也可以手动操作:
foreach (get_defined_vars() as $k => $v) {
$GLOBALS[$k] = $v;
}
根据您的确切需求,您可以使用常量。要求您的文件在全局范围内,但在其内部设置一个常量。
IE文件.php:
define('MY_CONSTANT', 42);
然后,在脚本中的任何地方,只要使用MY_CONSTANT
来引用该值,一旦设置好,就无法进行编辑。除此之外,你可以像另一个答案所说的那样全球化你的变量,但除了简单地从包含的文件中检索一个值之外,你还不能100%清楚你想要实现什么?在这种情况下,常数应该很好。
更新:现在你已经解释了你希望对象属性在任何地方都可用,我建议你考虑创建一个静态类,一旦在你的全局范围中实例化,它就可以在你的应用程序中的任何地方使用。阅读链接的手册页面,它有一个简单的例子。