Сохранение области действия PHP при вызове функции

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

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

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

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

В моем случае обращение к вашему «Edit 2» и простое использование include не сработало, потому что у меня происходит намного больше вещей. По сути, думайте об этом как о классе "View", которому требуется viewscript.php, который, поскольку мы находимся в области действия плагина, я хочу передать "глобальную" область видимости скрипту просмотра без необходимости объявлять каждую переменную как глобальную в " doInclude "функция.

Dustin Graham 24.02.2013 03:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
5
1
2 477
6

Ответы 6

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

// 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/

Would it be better to use extract($_GLOBALS); inside my function call instead?

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

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

wrong();        // undefined variable $x
right();        // "foo"

Это именно та проблема, с которой я столкнулся. Я пытаюсь разработать плагин для скрипта, но, к сожалению, этот скрипт делает некоторые странные вещи с глобальными переменными. Больно отслеживать все различные глобальные объекты, которые мне нужны, и объявлять их в функции «doInclude». Ну что ж ... Я думал, что $ GLOBALS подойдет, но это не работает из-за порядка функций и включает. Такова, наверное, жизнь разработчика плагина.

Dustin Graham 24.02.2013 03:12

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

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

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

У меня есть большинство переменных конфигурации, настроенных таким образом, но у меня есть массив кодов стран, объект базы данных и т. д., Которые не могут быть определены таким образом.

Joshua 03.10.2008 09:32

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

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

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

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

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

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

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

config.php

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

script.php

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

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

Is there any easier way to do this, i.e. by preserving scope when a function call is made

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

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

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

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

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

Это не ответ на вопрос, а скорее выражение «вы делаете это неправильно». Спасибо, Стив. Иногда бывают ситуации, когда бы было бы неплохо для запуска функции с использованием желаемой области видимости (т.е. глобальной). call_user_func_array_with_scope('function', $args, $this) был бы отличным, если бы он существовал ... (Или передавая "null" или global, чтобы передать ее в глобальную область. пригодится при создании плагина для работы с четко определенными ограничениями.

Dustin Graham 24.02.2013 03:20

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

//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";

Другие вопросы по теме