PHP сохранить область при вызове функции - PullRequest
5 голосов
/ 03 октября 2008

У меня есть функция, которая включает файл, основанный на строке, которая передается ему, то есть переменная действия из строки запроса. Я использую это для целей фильтрации и т. Д., Чтобы люди не могли включать файлы, которые они не должны иметь, и если файл не существует, вместо него загружается файл по умолчанию. Проблема заключается в том, что когда функция запускается и включает область файла, теряется, потому что include запускается внутри функции. Это становится проблемой, потому что я использую файл глобальной конфигурации, затем я использую определенные файлы конфигурации для каждого модуля на сайте. В настоящий момент я делаю это, определяя переменные, которые я хочу использовать как глобальные, а затем добавляя их в верхнюю часть функции фильтрации.

Есть ли более простой способ сделать это, т. Е. Сохранить область видимости при вызове функции или существует такая вещь, как PHP-макрос?

Редактировать: Было бы лучше использовать экстракт ($ _ GLOBALS); вместо вызова моей функции?

Редактировать 2: Для всех, кто заботился. Я осознал, что перестал думать об этой проблеме в целом, и что вместо использования функции мне просто нужно использовать include, да! Таким образом, я могу сохранить прицел и иметь свой торт тоже.

Ответы [ 6 ]

5 голосов
/ 03 октября 2008

Редактировать: Хорошо, я перечитал ваш вопрос и думаю, что понял, о чем вы сейчас говорите:
Вы хотите, чтобы что-то вроде этого работало:

// myInclude.php
$x = "abc";

// -----------------------
// myRegularFile.php

function doInclude() {
    include 'myInclude.php';
}
$x = "A default value";
doInclude();
echo $x;    // should be "abc", but actually prints "A default value"

Если вы изменяете только пару переменных и заранее знаете, какие переменные будут определены во включении, объявите их как global в функции doInclude().

В качестве альтернативы, если каждое из ваших включений может определять любое количество переменных, вы можете поместить их все в один массив:

// myInclude.php
$includedVars['x'] = "abc";
$includedVars['y'] = "def";

// ------------------
// myRegularFile.php
function doInclude() {
    global $includedVars;
    include 'myInclude.php';
    // perhaps filter out any "unexpected" variables here if you want
}

doInclude();
extract($includedVars);
echo $x;        // "abc"
echo $y;        // "def"

оригинальный ответ:

этот тип вещей известен как "замыкания" и вводится в PHP 5.3

http://steike.com/code/php-closures/

Было бы лучше использовать extract ($ _ GLOBALS); вместо вызова моей функции?

дорогой лорд, нет. если вы хотите получить доступ к глобальной переменной внутри функции, просто используйте ключевое слово global. например:

$x = "foo";
function wrong() {
    echo $x;
}
function right() {
    global $x;
    echo $x;
}

wrong();        // undefined variable $x
right();        // "foo"
0 голосов
/ 17 апреля 2010

Вы можете объявить переменные во включаемом файле как глобальные, гарантируя, что они имеют глобальную область действия:

//inc.php
global $cfg;
$cfg['foo'] = bar;

//index.php
function get_cfg($cfgFile) {
    if (valid_cfg_file($cfgFile)) {
        include_once($cfgFile);
    }
}
...
get_cfg('inc.php');
echo "cfg[foo]: $cfg[foo]\n";
0 голосов
/ 07 октября 2008

Есть ли более простой способ сделать это, т. Е. Сохранить область действия при вызове функции

Вы можете использовать:

function doInclude($file, $args = array()) {
  extract($args);
  include($file);
}

Если вы не хотите явно передавать переменные, вы можете вызвать doInclude с get_defined_vars в качестве аргумента, например ::

doInclude('test.template.php', get_defined_vars());

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

0 голосов
/ 03 октября 2008

Почему бы не вернуть значение из вашего include, а затем установить значение вызова include для переменной:

config.php

return array(
    'foo'=>'bar',
    'x'=>23,
    'y'=>12
);

script.php

$config = require('config.php');
var_dump($config);

Не нужно путать место с глобальными переменными

0 голосов
/ 03 октября 2008

Если я правильно понимаю, у вас есть код в виде:

function do_include($foo) {
  if (is_valid($foo))
    include $foo;
}

do_include(@$_GET['foo']);

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

if (is_valid(@$_GET['foo']))
  include $_GET['foo'];

Существуют и другие обходные пути (как вы упомянули: объявление глобальных переменных, непосредственная работа с массивом $ _GLOBALS и т. Д.), Но преимущество этого решения заключается в том, что вам не нужно запоминать такие соглашения во всех включенных файлах.

0 голосов
/ 03 октября 2008

Когда дело доходит до параметров конфигурации (особенно путей к файлам и т. Д.), Я обычно просто определяю их с помощью абсолютных путей, используя define (). Что-то вроде:

define('MY_CONFIG_PATH', '/home/jschmoe/myfiles/config.inc.php');

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...