Есть ли способ явно указать область применения require_once ()? - PullRequest
13 голосов
/ 23 января 2012

Я ищу способ установить область действия require_once() на глобальную область, когда require_once() используется внутри функции. Что-то вроде следующего кода должно работать:

файл `foo.php ':

<?php

$foo = 42;

фактический код:

<?php

function includeFooFile() {
    require_once("foo.php"); // scope of "foo.php" will be the function scope
}

$foo = 23;

includeFooFile();
echo($foo."\n"); // will print 23, but I want it to print 42.

Есть ли способ явно установить область действия require_once()? Есть хороший обходной путь?

Ответы [ 7 ]

5 голосов
/ 23 января 2012

Кроме «глобализации» вашей переменной, нет способа сделать это:

global $foo;
$foo = 42;

OR

$GLOBALS['foo'] = 42;

Тогда ваше значение должно быть 42, когда вы его распечатываете.

UPDATE

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

3 голосов
/ 23 января 2012

Это определенно не"хорошая" работа, но она будет работать:

function includeFooFile() {
  require_once("foo.php");
  foreach (get_defined_vars() as $key => $value) {
    // Ignore superglobals
    if (!in_array($key, array('GLOBALS','_SERVER','_GET','_POST','_FILES','_COOKIE','_SESSION','_REQUEST','_ENV'))) {
      $GLOBALS[$key] = $value;
    }
  }
}

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

РЕДАКТИРОВАТЬ очевидно, вы можете включить функции в свой файл. Я всегда думал, что ты не сможешь, но после тестирования кажется, что ты можешь.

3 голосов
/ 23 января 2012

Вам нужно будет объявить глобальный в вашем foo.php:

<?php
 global $foo;
 $foo = 42;
?>

В противном случае это, вероятно, невозможно.

Вы можете попробовать поиграться с extract(), get_defined_vars(), global и $GLOBALS в различных комбинациях, например ... например, перебирая все определенные переменные и вызывая их глобально, прежде чем запрашивать файл ...

$vars = get_defined_vars();
foreach($vars as $varname => $value)
{
  global $$varname; //$$ is no mistake here
}
require...

Но я не совсем уверен, попадете ли вы туда, куда хотите ...

2 голосов
/ 23 января 2012

Поскольку область действия явно указана, когда вы используете require и т. П., Вам нужно будет указать, что делать с переменными внутри области действия функции:

function includeFooFile() {
    require_once("foo.php"); // scope of "foo.php" will be the function scope

    foreach (get_defined_vars() as $k => $v)
    {
        $GLOBALS[$k] = &$v;
    }
}

Этот пример заботитсяпеременных и ссылок, которые могут быть тем, что вы ищете. Демо .Обратите внимание, что require_once будет работать только один раз и будет определять переменные только один раз.

1 голос
/ 14 мая 2015

Вы можете использовать эту хакерскую функцию, которую я написал:

/**
 * Extracts all global variables as references and includes the file.
 * Useful for including legacy plugins.
 *
 * @param string $__filename__ File to include
 * @param array  $__vars__     Extra variables to extract into local scope
 * @throws Exception
 * @return void
 */
function GlobalInclude($__filename__, &$__vars__ = null) {
    if(!is_file($__filename__)) throw new Exception('File ' . $__filename__ . ' does not exist');
    extract($GLOBALS, EXTR_REFS | EXTR_SKIP);
    if($__vars__ !== null) extract($__vars__, EXTR_REFS);
    unset($__vars__);
    include $__filename__;
    unset($__filename__);
    foreach(array_diff_key(get_defined_vars(), $GLOBALS) as $key => $val) {
        $GLOBALS[$key] = $val;
    }
}

Перемещает все вновь определенные переменные обратно в глобальное пространство, когда возвращается включаемый файл. Существует оговорка, что если включенный файл включает в себя другой файл, он не сможет получить доступ к любым переменным, определенным в родительском файле, через $GLOBALS, поскольку они еще не были глобализированы.

1 голос
/ 23 января 2012

Я не пробовал (поскольку использовать глобальные переменные - плохая идея), но это может сработать:

require_once '...';
$GLOBALS = array_merge($GLOBALS, get_defined_vars());

В качестве альтернативы вы можете просто сделать это вручную:

foreach (get_defined_vars() as $k => $v) {
    $GLOBALS[$k] = $v;
}
1 голос
/ 23 января 2012

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

IE file.php:

define('MY_CONSTANT', 42);

Тогда в любом месте вашего скрипта просто используйте MY_CONSTANT для ссылки на значениеВы не сможете редактировать, как только он будет установлен.Кроме этого, вы можете глобализировать свою переменную, как говорится в другом ответе, но не ясно на 100%, чего вы пытаетесь достичь, кроме простого извлечения значения из включенного файла?В этом случае с константами должно быть все в порядке.

Обновление: Теперь вы объяснили, что хотите, чтобы свойства объектов были доступны везде, и я предлагаю вам взглянуть на создание статического класса ., который когда-то был создан в вашей глобальной области видимости и может использоваться в любом месте вашего приложения.Прочитайте ссылку на справочную страницу, на ней приведен простой пример.

...