函数内部不能访问全局变量

时间:2022-05-12 19:55:31

This (simplified version of my code) doesn't work:

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

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

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

    foo();
?>

Why? I want to access $sxml because I want to log errors on it if foo() fails. foo() calls itself recursively to create a directory listing, so I fear passing the whole $sxml onto itself (as in foo($sxml)) could hurt performance.

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

Is there a way to access $sxml inside $foo without passing it as an argument? (PHP 5.2.x+)

是否有一种方法可以在$foo中访问$sxml而不将其作为参数传递?(PHP 5.2.x +)

EDIT: What if the code looks like this, actually?

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

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

5 个解决方案

#1


102  

You have to pass it to the function:

你必须把它传递给函数:

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

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

    foo($sxml);
?>

or declare it global:

或声明它全球:

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

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

    foo();
?>

If the variable isn't global but is instead defined in an outer function, the first option (passing as an argument) works just the same:

如果变量不是全局变量,而是在外部函数中定义的,那么第一个选项(作为参数传递)的工作原理是一样的:

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

Alternatively, create a closure by declaring the variable in a use clause.

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

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

#2


19  

You need to explicitly invite the global variable into the functions scope:

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

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

#3


4  

Use the global keyword to declare $sxml inside your function.

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

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

#4


3  

another solution is to use $GLOBALS while you declare that variable:

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

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

#5


2  

While the top answer provides a nice solution, I'd like to argue that the appropriate solution in most modern PHP applications is to create a class with a static variable, like so:

虽然上面的答案提供了一个不错的解决方案,但我想指出,在大多数现代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();

This approach allows you to access $sxml from within foo() just like you wanted, but it has a few advantages over the global approach.

这种方法允许您像希望的那样从foo()中访问$sxml,但是它比全局方法有一些优势。

  1. With this strategy, you will always be able to put a breakpoint inside setXML() to find out what part of your application has manipulated this value, which you cannot do when manipulating globals.
  2. 使用此策略,您将始终能够在setXML()中放置断点,以查明应用程序的哪个部分操纵了这个值,这是在操作全局变量时无法做到的。
  3. You avoid polluting the global namespace with a generic variable name sxml.
  4. 避免使用通用变量名称sxml污染全局名称空间。

#1


102  

You have to pass it to the function:

你必须把它传递给函数:

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

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

    foo($sxml);
?>

or declare it global:

或声明它全球:

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

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

    foo();
?>

If the variable isn't global but is instead defined in an outer function, the first option (passing as an argument) works just the same:

如果变量不是全局变量,而是在外部函数中定义的,那么第一个选项(作为参数传递)的工作原理是一样的:

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

Alternatively, create a closure by declaring the variable in a use clause.

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

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

#2


19  

You need to explicitly invite the global variable into the functions scope:

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

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

#3


4  

Use the global keyword to declare $sxml inside your function.

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

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

#4


3  

another solution is to use $GLOBALS while you declare that variable:

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

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

#5


2  

While the top answer provides a nice solution, I'd like to argue that the appropriate solution in most modern PHP applications is to create a class with a static variable, like so:

虽然上面的答案提供了一个不错的解决方案,但我想指出,在大多数现代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();

This approach allows you to access $sxml from within foo() just like you wanted, but it has a few advantages over the global approach.

这种方法允许您像希望的那样从foo()中访问$sxml,但是它比全局方法有一些优势。

  1. With this strategy, you will always be able to put a breakpoint inside setXML() to find out what part of your application has manipulated this value, which you cannot do when manipulating globals.
  2. 使用此策略,您将始终能够在setXML()中放置断点,以查明应用程序的哪个部分操纵了这个值,这是在操作全局变量时无法做到的。
  3. You avoid polluting the global namespace with a generic variable name sxml.
  4. 避免使用通用变量名称sxml污染全局名称空间。