Не удается получить доступ к глобальной переменной внутри функции - PullRequest
56 голосов
/ 27 марта 2011

Это (упрощенная версия моего кода) не работает:

<?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 ]

110 голосов
/ 27 марта 2011

Вы должны передать его в функцию:

<?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пункт.

<?php
    function bar() {
        $sxml = new SimpleXMLElement('<somexml/>');
        function foo() use(&$xml) {
            $child = $sxml->addChild('child');
        }
        foo();
    }
    bar();
?>
20 голосов
/ 27 марта 2011

Вам необходимо явно пригласить глобальную переменную в область действия функций:

function foo(){
    global $sxml;
    $child = $sxml->addChild('child');
}
4 голосов
/ 27 марта 2011

Используйте ключевое слово global для объявления $ sxml внутри вашей функции.

<?php
    $sxml = new SimpleXMLElement('<somexml/>');
    function foo(){
    global   $sxml;  
    $child = $sxml->addChild('child');
    }
    foo();
?>
3 голосов
/ 25 марта 2018

Хотя верхний ответ дает хорошее решение, я бы хотел сказать, что подходящее решение в большинстве современных 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.
3 голосов
/ 11 мая 2015

другое решение заключается в использовании $ GLOBALS при объявлении этой переменной:

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