【问题标题】:Can't access global variable inside function无法访问函数内部的全局变量
【发布时间】:2011-07-23 21:36:30
【问题描述】:

这(我的代码的简化版本)不起作用:

<?php
    $sxml = new SimpleXMLElement('<somexml/>');

    function foo(){
        $child = $sxml->addChild('child');
    }

    foo();
?>

为什么?我想访问$sxml,因为如果foo() 失败,我想在上面记录错误。 foo() 递归调用自身以创建目录列表,所以我担心将整个 $sxml 传递给自身(如在 foo($sxml) 中)可能会损害性能。

有没有办法访问$foo 内部的$sxml 而无需将其作为参数传递? (PHP 5.2.x+)

编辑:如果代码实际上是这样的呢?

<?php
    bar(){
        $sxml = new SimpleXMLElement('<somexml/>');
        function foo(){
            $child = $sxml->addChild('child');
        }
        foo();
    }
    bar();
?>

【问题讨论】:

  • 请执行 OOP 或将其作为参数传递。可重用性是关键。
  • @thephpdeveloper 我理解你的意思,但我刚刚开始使用 PHP,这可能不是我将重用的代码。它更像是一个原型,如果出现问题,我可以扔掉并从头开始。

标签: php variables scope global-variables


【解决方案1】:

你必须将它传递给函数:

<?php
    $sxml = new SimpleXMLElement('<somexml/>');

    function foo($sxml){
        $child = $sxml->addChild('child');
    }

    foo($sxml);
?>

或声明global:

<?php
    $sxml = new SimpleXMLElement('<somexml/>');

    function foo(){
        global $sxml;
        $child = $sxml->addChild('child');
    }

    foo();
?>

如果变量不是全局变量而是在外部函数中定义的,第一个选项(作为参数传递)的作用相同:

<?php
    function bar() {
        $sxml = new SimpleXMLElement('<somexml/>');
        function foo($sxml) {
            $child = $sxml->addChild('child');
        }
        foo($sxml);
    }
    bar();
?>

或者,通过在use 子句中声明变量来创建closure

<?php
    function bar() {
        $sxml = new SimpleXMLElement('<somexml/>');
        function foo() use(&$xml) {
            $child = $sxml->addChild('child');
        }
        foo();
    }
    bar();
?>

【讨论】:

  • 还有一件事......如果变量在父函数中怎么办? (问题已编辑):(
  • 在第二个示例中,您无法从 foo() 访问 $sxml,因为它是在 bar() 中本地定义的。一个解决方案可能是:在 foo() 和 bar() 之外声明 $sxml,并在两个函数中使用 global。但正如 phpdeveloper 所建议的,你应该使用 OOP ;)
【解决方案2】:

您需要显式邀请全局变量进入函数范围:

function foo(){
    global $sxml;
    $child = $sxml->addChild('child');
}

【讨论】:

    【解决方案3】:

    使用 global 关键字在函数中声明 $sxml。

    <?php
        $sxml = new SimpleXMLElement('<somexml/>');
        function foo(){
        global   $sxml;  
        $child = $sxml->addChild('child');
        }
        foo();
    ?>
    

    【讨论】:

      【解决方案4】:

      另一种解决方案是在声明该变量时使用 $GLOBALS

               $my_var   = 'blabla';    // not global
      $GLOBALS['my_var'] = 'blabla';    // global  (correct)
      

      【讨论】:

        【解决方案5】:

        虽然上面的答案提供了一个很好的解决方案,但我想说的是,在大多数现代 PHP 应用程序中,适当的解决方案是创建一个带有静态变量的类,如下所示:

        <?php
        
        class xmlHelper {
            private static $sxml;
        
            public function getXML() {
                return self::$sxml;
            }
        
            public function setXML($xml) {
                self::$sxml = $xml;
            }
        }
        
        xmlHelper::setXML(new SimpleXMLElement('<somexml/>'));
        
        function foo(){
            $child = xmlHelper::getXML()->addChild('child');
        }
        
        foo();
        

        这种方法允许您从foo() 中访问$sxml,就像您想要的那样,但它比global 方法有一些优势。

        1. 使用此策略,您将始终能够在 setXML() 中放置一个断点,以找出您的应用程序的哪个部分操纵了该值,而在操纵全局变量时您无法做到这一点。
        2. 避免使用通用变量名称 sxml 污染全局命名空间。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多