PHP: «Глобальный» включает - PullRequest
       40

PHP: «Глобальный» включает

4 голосов
/ 15 апреля 2009

Текущая ситуация:

  • У меня есть текущая версия моей MVC Framework, которая использует классы в качестве контроллеров.
  • У меня есть несколько «винтажных» модулей из моей старой MVC Framework, в которой в качестве контроллеров используются простые плоские включения.

Гораздо проще, что означает:

Новая версия:

<?PHP
class blaController extends baseController {
    private $intVar;

    function dosomethingFunction() {
        $this->intVar = 123;
        $this->view('myView');
    }
}
?>

Старая версия:

<?PHP
$globalVar = 123;
// view "controllername" is automatically shown
?>

Я сейчас пытаюсь написать оболочку, чтобы иметь возможность использовать мои старые контроллеры в моем новом MVC без необходимости переписывать все. Для этого у меня есть контроллер "обертка":

class wrapController extends baseController {
    function dosomethingFunction() {
        require 'old_dosomething.function.php';
        $this->view('old_dosomething_view');
    }
}

(Еще раз: это ОЧЕНЬ, ОЧЕНЬ упрощено - просто чтобы закончить идею. Не фактический код.)

Проблема этого подхода состоит в том, что ранее глобальная переменная $ globalVar теперь существует только внутри метода "dosomethingFunction" и не может быть доступна представлению.

Это было бы не так, если бы я мог заставить требование вести себя как "в глобальной области видимости", чтобы $ globalVar снова был доступен в глобальной области видимости.

Итак: есть ли какой-нибудь способ добиться " require_global " или чего-то подобного?

(Одним из решений моей проблемы было бы модифицировать мои старые контроллеры так, чтобы они запускались с помощью набора «глобальных» команд, но я бы предпочел решение, в котором мне не нужно менять так много старого кода.)

(Примечание. Пожалуйста, не говорите мне, что GLOBALS - это плохо. Он полностью не отвечает сути этого вопроса. Просто примите, что необходимо, чтобы какой-то старый код работал в новой, более чистой среде.)

Ответы [ 5 ]

6 голосов
/ 15 апреля 2009

Вы можете добавить локальные переменные, определенные в dosomethingFunction (), в глобальную область:

class wrapController extends baseController {
    function dosomethingFunction() {
        require 'old_dosomething.function.php';
        //begin added code  
        $vararr = get_defined_vars();
        foreach($vararr as $varName => $varValue) 
              $GLOBALS[$varName] = $varValue;            
        //end added code          
        $this->view('old_dosomething_view');
    }
}

Обратите внимание, что для того, чтобы это работало должным образом, вы должны вызвать require, прежде чем использовать какую-либо другую функцию в функции. get_defined_vars () возвращает только переменные из текущей области, поэтому взломы array_diff не нужны.

4 голосов
/ 15 апреля 2009

Это самое простое решение, которое я могу придумать.

Дважды воспользуйтесь функцией get_defined_vars () и получите diff каждого вызова, чтобы определить, какие переменные были введены требуемым файлом.

Пример:

$__defined_vars       = get_defined_vars();
require('old_dosomething.function.php');
$__newly_defined_vars = array_diff_assoc($__defined_vars, get_defined_vars());
$GLOBALS = array_merge($GLOBALS, $__newly_defined_vars);
$this->view('old_dosomething_view');
1 голос
/ 15 апреля 2009

Для всех, кто заинтересован: Моя (пока) окончательная версия:

class wrapController extends baseController {
    function dosomethingFunction() {
        // ... do some initialisation stuff ...

        $__defined_vars = array_keys(get_defined_vars());

        require 'old_dosomething.function.php';

        $__newly_defined_vars = array_diff(
                                    array_keys(get_defined_vars()),
                                    $__defined_vars, 
                                    array('__defined_vars')
                                );
        foreach ($__newly_defined_vars as $var) {
            $GLOBALS[$var] = &$$var;
        }

        $this->view('old_dosomething_view');
    }
}

Ужасно, но это работает. Спасибо за вашу большую помощь!

1 голос
/ 15 апреля 2009

Хммм, это проблема, которую я никогда раньше не видел. Я полагаю, вы могли бы сделать это

class wrapController extends baseController {
    function dosomethingFunction() {
        require 'old_dosomething.function.php';

        // Force "old" globals into global scope
        $GLOBALS['globalVar'] = $globalVar;

        $this->view('old_dosomething_view');
    }
}

Но это довольно утомительный, ручной процесс, в зависимости от того, сколько глобалов мы говорим. Я подумаю об этом, но я не знаю ни одного "автомагического" решения на моей голове.

0 голосов
/ 15 апреля 2009

Вы пробовали Zend_Registry из Zend Framework?

Реестр - это контейнер для хранения объектов и значений в пространстве приложения. Сохраняя значение в реестре, один и тот же объект всегда доступен во всем приложении. Этот механизм является альтернативой использованию глобального хранилища.

http://framework.zend.com/manual/en/zend.registry.html

...