【问题标题】:Is there a way to set the scope of require_once() explicitly to global?有没有办法将 require_once() 的范围显式设置为全局?
【发布时间】: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()

标签: php scope global-variables 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 访问父文件中定义的任何变量,因为它们还没有被全球化。

    【讨论】:

      猜你喜欢
      • 2021-01-04
      • 2011-02-28
      • 2018-07-01
      • 1970-01-01
      • 2019-11-13
      • 2012-04-29
      • 2015-09-27
      • 2014-07-04
      相关资源
      最近更新 更多