无法访问函数内部的全局变量

Posted

技术标签:

【中文标题】无法访问函数内部的全局变量【英文标题】: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,这可能不是我将重用的代码。它更像是一个原型,如果出现问题,我可以扔掉并从头开始。 【参考方案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 方法有一些优势。

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

【讨论】:

以上是关于无法访问函数内部的全局变量的主要内容,如果未能解决你的问题,请参考以下文章

C#全局作用符::

JS封闭函数闭包内置对象

闭包与垃圾回收机制

访问函数内部的变量,使用“this”关键字初始化

无法从另一个函数(在全局范围内定义)访问变量(数组)

scriptProcessorNode.onaudioprocess 无法访问全局变量