有没有办法将 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() 的范围显式设置为全局?的主要内容,如果未能解决你的问题,请参考以下文章

PHP - 类构造中的Require_once

重命名 require_once 函数的策略?

PHP学习笔记 - includerequireinclude_once 和 require_once的区别

求关于php excel导入大数据到mysql的解决办法

有没有办法确定作业运行的“起点”?

在setupBeforeClass之后有没有办法执行dataprovider函数?