Возможно ли получить переменные с помощью get_defined_vars(), но для фактического запущенного скрипта?

#php #variables #scope #defined

#php #переменные #область видимости #определено

Вопрос:

Я пытаюсь создать функцию для получения всех пользовательских переменных для выборочного их сброса до фактического завершения скрипта. Чтобы получить все используемые переменные, вы должны использовать get_defined_vars() функцию, которую предоставляет вам PHP, но у нее есть предостережение (по крайней мере, для меня …): она работает только в той области, в которой она фактически вызвана.

Я хотел бы, в идеале, инкапсулировать его в функцию внутри моего основного пространства имен framework, HelpersCore таким образом, функция будет HelpersCoregetVariables() .

На самом деле, мой код выглядит так:

 foreach (array_diff(array_keys(get_defined_vars()), ["_COOKIE", "_ENV", "_FILES", "_GET", "_POST", "_REQUEST", "_SERVER", "_SESSION", "argc", "argv", "GLOBALS", "HTTP_RAW_POST_DATA", "http_response_header", "ignore", "php_errormsg"], ["page"]) as $variable) {
    unset($variable);
}
 

По сути, он пытается автоматизировать выбор переменных с помощью:

  • получение всех имен переменных с помощью array_keys(get_defined_vars())
  • определение набора зарезервированных или общесистемных переменных, таких как $_GET , $_POST , $_SERVER и так далее
  • при условии, какие из ваших используемых переменных сохранены (в этом примере, $page )

Проблема в том, что я не хотел бы размещать этот код везде, где я хочу избавиться от некоторых переменных. В идеале я хотел бы иметь возможность определить это как функцию и автоматизировать ее использование, но … есть ли способ выполнить это, но в текущем скрипте, из которого вы вызываете функцию?

Комментарии:

1. Используйте $GLOBAL для получения переменных в глобальной области видимости и передачи результата get_defined_vars в качестве аргумента вашей функции.

2. может быть, вы можете сохранить в сеансе или файле cookie?

3. Это то, что я имел в виду … функция для вставки некоторых имен переменных $_SESSION , поэтому вместо третьего члена ["page"] (как в примере выше) его можно автоматизировать, указав что-то подобное HelpersCoregetVariables() или подобное. Я хотел избежать выполнения большего количества шагов, чем на самом деле необходимо, но, возможно, это единственный «гарантированный» способ его работы…

Ответ №1:

Вы можете использовать $GLOBALS вместо get_defined_vars() для доступа к глобальной области видимости и для отмены установки глобальных переменных:

 $non_user_vars = ["_COOKIE", "_ENV", "_FILES", "_GET", "_POST", "_REQUEST", 
                  "_SERVER", "_SESSION", "argc", "argv", "GLOBALS",
                  "HTTP_RAW_POST_DATA", "http_response_header",
                  "ignore", "php_errormsg"];

$safe_user_vars = ["page"];

$all_vars = array_keys($GLOBALS);

$user_vars = array_diff($all_vars, $non_user_vars, $safe_user_vars);

foreach($user_vars as $variable) {
    unset($GLOBALS[$variable]);
}
 

Быстрые предостережения к этому подходу:

  1. чтобы сделать его более чистым, я сначала определил массивы. Это может привести к их попаданию в ваш $user_vars массив (думал, что этого не должно быть, если они не являются глобальными), поэтому защищайтесь от этого, чтобы избежать возникновения ошибки или других последствий.
  2. Ваш массив непользовательских переменных не является исчерпывающим, так как, когда я тестировал выше, я все равно получил:
     Array
    (
        [2] => HTTP_ENV_VARS
        [6] => HTTP_POST_VARS
        [8] => HTTP_GET_VARS
        [10] => HTTP_COOKIE_VARS
        [12] => HTTP_SERVER_VARS
        [14] => HTTP_POST_FILES
        [16] => test
        [17] => non_user_vars
    )
     

Если вы не хотите угадывать, что предопределено или видно во время выполнения, возможно, может быть начальный вызов HelpersCoregetVariables() , который получает список переменных и сохраняет их статически, поэтому вам array_diff просто нужно сравнить начальный список со списком в конце, чтобы узнать, что определено пользователем.

Комментарии:

1. Хорошо, теперь это другая история. У меня не было цели для $GLOBALS, пока я не запустил ваш пример. Извините за путаницу и большое вам спасибо за подсказку. Теперь метод работает отлично! Я должен тебе пиво 🙂