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

时间:2011-03-27 13:34:10

标签: php variables scope global-variables

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

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

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

    foo();
?>

为什么呢?我想访问$sxml,因为如果foo()失败,我想在其上记录错误。 foo()以递归方式调用自己来创建目录列表,因此我担心将整个$sxml传递给自身(如在foo($sxml)中)可能会影响性能。

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

编辑:如果代码看起来像这样,怎么办?

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

5 个答案:

答案 0 :(得分:108)

您必须将其传递给函数:

<?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();
?>

答案 1 :(得分:20)

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

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

答案 2 :(得分:4)

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

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

答案 3 :(得分:3)

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

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

答案 4 :(得分:3)

虽然最佳答案提供了一个很好的解决方案,但我想说大多数现代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();

此方法允许您按照自己的需要从$sxml内访问foo(),但与global方法相比,它有一些优势。

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