【问题标题】:Access a global variable in a PHP function访问 PHP 函数中的全局变量
【发布时间】:2013-03-19 05:12:39
【问题描述】:

根据大多数编程语言的作用域规则,我可以访问在它们内部的函数之外定义的变量,但为什么这段代码不起作用?

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $data . "]";
    }

    menugen();
?>

输出是[]

【问题讨论】:

  • 不要将其视为全局,将其作为参数传递给函数
  • 手册哪里有这样的说法?
  • 相关阅读:PHP global in functions
  • 查看本页的第二个例子:php.net/manual/en/language.variables.scope.php
  • afaik 我们可以使用 $GLOBALS['varname'] 访问,其中索引“varname”是函数外的 $varname。事实上我们可以使用 print_r($GLOBALS) 查看所有全局变量。

标签: php scope


【解决方案1】:

由于这个原因,PHP 可能会令人沮丧。上面使用global 的答案对我不起作用,我花了一段时间才弄清楚use 的正确用法。

这是正确的:

$functionName = function($stuff) use ($globalVar) {
 //do stuff
}
$output = $functionName($stuff);
$otherOutput = $functionName($otherStuff);

这是不正确的:

function functionName($stuff) use ($globalVar) {
 //do stuff
}
$output = functionName($stuff);
$otherOutput = functionName($otherStuff);

使用您的具体示例:

    $data = 'My data';

    $menugen = function() use ($data) {
        echo "[" . $data . "]";
    }

    $menugen();

【讨论】:

    【解决方案2】:

    多年来我一直使用这种格式:

    <?php
        $data = "Hello";
    
        function sayHello(){
            echo $GLOBALS["data"];
        }
    
        sayHello();
    ?>
    

    我觉得它简单易懂。 $GLOBALS 是 PHP 让您引用全局变量的方式。如果您使用过 $_SERVER、$_POST 等,那么您在不知情的情况下引用了一个全局变量。

    【讨论】:

    • 哪一个? $GLOBAL(文本)还是$GLOBALS(示例代码)? (请通过editing your answer 回复,而不是在 cmets 中(视情况而定)。)
    • 这是 $GLOBALS 而不是 $GLOBAL。应该有一个“S”。然后像关联数组的键一样引用您的变量名。
    • update your answer by editing it(开始the editing,点击edit,在“share”之间flag"。这三个在左侧 - "edited""answered" 的左侧,在答案本身之后,在此评论上方,以及最重要的是这里的三个 cmets)。 cmets 中的信息随时可能消失。这不是论坛 - 信息可以(并且应该)在此处更新。非常感谢您。
    【解决方案3】:

    另一种方法:

    <?php
    
    $data = 'My data';
    
    $menugen = function() use ($data) {
    
        echo "[".$data."]";
    };
    
    $menugen();
    

    2020-01-13 更新:彼得莫滕森要求

    从 PHP 5.3.0 开始,我们支持可以创建闭包的匿名函数。闭包可以访问在其范围之外创建的变量。

    在示例中,闭包能够访问$data,因为它是在use 子句中声明的。

    【讨论】:

    • 在我的案例中,这是唯一可行的解​​决方案,我将一个函数定义为另一个函数中的变量。 Global 在那里不起作用。
    • 解释一下。例如,这个“使用”的东西是做什么的?这个“使用”的东西支持哪些 PHP 版本? (请通过editing your answer 回复,而不是在 cmets 中(视情况而定)。提前致谢。)
    • 不知道为什么批准的 ans 在 Wordpress 管理插件页面中没有显示任何输出,但这个 ans 运行良好。
    【解决方案4】:
    <?php
    
        $data = 'My data';
    
        $menugen = function() use ($data) {
    
            echo "[ $data ]";
        };
    
        $menugen();
    ?>
    

    你也可以简化

    echo "[" . $data . "]"
    

    echo "[$data]"
    

    【讨论】:

    • echo "[" . $data . "]"echo "[ $data ]" 不一样(后者的输出中有两个额外的空格)。
    【解决方案5】:

    您可以执行以下操作之一:

    <?php
        $data = 'My data';
    
        function menugen() {
            global $data;
            echo "[" . $data . "]";
        }
    
        menugen();
    

    或者

    <?php
        $data = 'My data';
    
        function menugen() {
            echo "[" . $GLOBALS['data'] . "]";
        }
    
        menugen();
    

    话虽如此,过度使用全局变量会导致一些糟糕的代码。通常最好传递你需要的东西。例如,您应该将一个句柄传递给数据库并对其进行操作,而不是引用一个全局数据库对象。这称为dependency injection。当您实施自动化测试(您应该这样做)时,它会让您的生活变得更轻松。

    【讨论】:

      【解决方案6】:

      这是范围问题。总之,应该避免全局变量所以

      您要么需要将其作为参数传递:

      $data = 'My data';
      
      function menugen($data)
      {
          echo $data;
      }
      

      或者将它放在一个类中并访问它

      class MyClass
      {
          private $data = "";
      
          function menugen()
          {
              echo this->data;
          }
      
      }
      

      也请参阅@MatteoTassinari 答案,因为您可以将其标记为全局以访问它,但通常不需要全局变量,因此重新考虑您的编码是明智的。

      【讨论】:

      • 另一种方法是使用关键字global(当然,这不是最好的方法)。
      • “应该”没有回答这个问题,这可能不是每个案例的最佳方法。对于简单的脚本,更改参数和添加类是很麻烦的。与 JavaScript 非常相似,在 PHP 中,并非所有内容都需要面向对象并在 wazoo 中命名。
      • @Beejor 鉴于 OP 有一个名为 menugen() 的函数,这意味着将不仅仅是生成一个菜单。例如,如何扩展该菜单以添加来自不同来源的更多项目,如何选择菜单中当前选定的页面。到处都有随机的全局变量和逻辑,这对 OOP 设计来说是一种尖叫。 PHP / JS 不需要结构化这一事实是您发现大量杂乱笨拙代码的最大原因之一。它可以做得很好,但让人们不必考虑未来的可维护性。
      • 它可能为隐含的问题提供了解决方案,但并没有真正回答原始问题,即如何访问函数中的全局变量。这就是人们通过网络搜索进入此页面的方式。
      • @Beejor - 这个论点的问题在于人们可能认为他们需要一个全局变量,因为他们不知道更好,除非他们知道被告知。
      【解决方案7】:

      它不起作用,因为您必须声明您将访问哪些全局变量:

      $data = 'My data';
      
      function menugen() {
          global $data; // <-- Add this line
      
          echo "[" . $data . "]";
      }
      
      menugen();
      

      否则,您可以使用$GLOBALS['data'] 访问它。请参阅Variable scope

      即使有点离题,我建议您完全避免使用全局变量,而更喜欢作为参数传递。

      【讨论】:

      • 谢谢,你是对的,但他们没有在手册的第二个例子中使用这一行:php.net/manual/en/language.variables.scope.php
      • 事实上,第二个例子是为了向读者展示该做什么:This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope.
      • 该死!我必须登录才能投票赞成这个答案,因为我令人毛骨悚然地忘记了 php 变量范围。
      【解决方案8】:

      你需要将变量传递给函数:

      $data = 'My data';
      
      function menugen($data)
      {
          echo $data;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多