Может ли встроенный PHP файл узнать, откуда он был включен?
Например,
Это index.php
<?
require_once('header.php');
?>
Может ли header.php знать, что он был включен index.php?
- EDIT -
Я нашел решение:
function backtrace_filename_includes($name){
$backtrace_array=debug_backtrace();
if (strpos($backtrace_array[1]['file'],$name)==false){
return false;
}else{
return true;
}
}
header.php
<?
if (backtrace_filename_includes('index.php')) echo "index.php";
?>
Ответы
Ответ 1
В то время как $_SERVER['PHP_SELF']
будет содержать текущий script, не существует способа определить из включенного файла, который определен script вызвало включение.
Это означает, что если a.php
включает b.php
, который включает в себя c.php
, c.php
не будет знать, что b.php
является включенным. Лучшее, что вы можете получить, это то, что a.php
является исполняемым в настоящее время script.
Изменить: Yup, мой вышеприведенный ответ технически неверен - вы можете использовать debug_backtrace
, чтобы найти вызывающего, даже без функций, до PHP 5.4, который удаляет эту функциональность.
a.php:
<?php
echo 'A';
include 'b.php';
b.php:
<?php
echo 'B';
include 'c.php';
c.php:
<?php
echo 'C';
print_r(debug_backtrace());
Вывод:
ABCArray
(
[0] => Array
(
[file] => /tmp/b.php
[line] => 3
[function] => include
)
[1] => Array
(
[file] => /tmp/a.php
[line] => 3
[args] => Array
(
[0] => /tmp/b.php
)
[function] => include
)
)
Итак, пока это работает, вы, вероятно, не должны его использовать. debug_backtrace
может быть заметным перетаскиванием производительности при чрезмерном использовании.
Ответ 2
get_included_files()
предоставляет стек включенных файлов в том порядке, в котором они включены, что в моем случае дало мне все, что мне нужно.
В частности, если вы вызываете get_included_files()
в файл, который был включен, этот собственный файл-путь этого файла будет самой последней записью в стеке, возвращаемой get_included_files()
, тот, который включил его, находится выше этого, и т.д..
Предостережение состоит в том, что файлы перечисляются только один раз, поэтому, если один и тот же файл включен более одного раза, в стеке будут отображаться только первые включенные. Для моих целей это не было проблемой, но это определенно означает, что это не будет работать во всех случаях.
Конкретный пример: представьте, что файл "test1.php" включает в себя "test_include.php". Результат get_included_files() с точки зрения "test_include.php" после загрузки test1.php в браузере выглядит следующим образом (учитывая, что, как видите, у меня есть файл auto_prepend, который, в свою очередь, загружает автозагрузчик).
array(4) {
[0]=>
string(21) "/www/auto_prepend.php"
[1]=>
string(19) "/www/autoloader.php"
[2]=>
string(14) "/www/test1.php"
[3]=>
string(21) "/www/test_include.php"
}
Так что test_include.php должен сделать немного array_pop'ing, чтобы выяснить, кто его включил.
Ответ 3
$_SERVER['PHP_SELF']
должен по-прежнему указывать на исходный доступ к файлу или вы можете установить переменную перед требованием, например:
$section = 'home';
require_once('header.php');
...
if ($section == 'home') {
...
}
Ответ 4
PHP отслеживает файл, который делает включение для вас в backtrace. С помощью небольшой вспомогательной функции вы можете получить имя файла, в котором была последняя команда include:
/**
* get filename that included this file
*
* @return string filename
*/
function include_by() {
$bt = debug_backtrace(0);
while ($b = array_shift($bt)) {
if (in_array($b['function'], array('require', 'require_once', 'include', 'include_once'), 1)) {
return $b['file'];
}
}
throw new BadFunctionCallException('Not an include.');
}
Использование:
main.php:
<?php
include('sub.php');
sub.php:
<?php
echo basename(include_by()); # main.php
См. также соответствующее использование backtrace: Функция Caller в PHP 5?.
Ответ 5
debug_print_backtrace();
Проверка документа PHP
Ответ 6
Самый простой способ в среде веб-сервера: $_SERVER['SCRIPT_FILENAME']
покажет исходный файл, который вызывается.
Универсальный путь - debug_backtrace()
покажет вам все предыдущие шаги выполнения, в которые будут включены вызовы функций require/include.