Can't access global variable inside function

Camilo Martin picture Camilo Martin · Mar 27, 2011 · Viewed 90.1k times · Source

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.

Is there a way to access $sxml inside $foo without passing it as an argument? (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();
?>

Answer

Javi R picture Javi R · Mar 27, 2011

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.

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