2009-04-15 2 views
4

Текущей ситуации:PHP: "Global" Включить

  • я имею текущую версию моей 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

Вы можете добавить локальные переменные, определенные в 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'); 
    } 
} 

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

+0

Я еще не знаю почему, но каким-то образом array_merge не работает в моем сценарии при слиянии массива «вручную» с работами foreach. – BlaM

+0

хорошо, $ GLOBAL на самом деле не «нормальный» массив. Вернулся к версии foreach. – vartec

1

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

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

"$ GLOBALS ['globalVar'] = $ globalVar;" было бы вариантом, если бы я мог выполнять итерацию по всем локальным переменным, но есть ли «автоматизированный» способ найти все это? – BlaM

4

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

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

Пример:

$__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'); 
+0

не нужно делать array_diff, если вы вызываете это из функции. get_defined_vars() возвращает только переменные в текущей области. – vartec

+0

Хорошая точка. Хотя, конечно, возможно, что кто-то позже добавляет переменные к этой функции. – Matt

+0

array_diff_assoc терпит неудачу, если одна из переменных - объект, который не может быть преобразован в строку. – BlaM

0

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

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

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

+0

Это потребует изменения старого кода, которого я стараюсь избегать. – BlaM

+0

... и я не вижу, как Zend_Registry лучше, чем простой глобальный массив для хранения файлов ... – BlaM

1

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

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'); 
    } 
} 

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

Смежные вопросы