Получить имя вызываемого файла из include ()

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

Я знаю, что __FILE__ волшебная константа __FILE__ , но это не помогает, так как она возвращает имя включенного файла, а не включающего его.

Есть какой-либо способ сделать это? Или это невозможно из-за того, как интерпретируется PHP?

Это на самом деле просто частный случай того, что делают PHP-шаблоны. Рассмотрим эту функцию:

 function ScopedInclude($file, $params = array()) { extract($params); include $file; } 

Тогда A.php может включать C.php следующим образом:

 <?php // A.php ScopedInclude('C.php', array('includerFile' => __FILE__)); 

Кроме того, B.php может включать C.php таким же образом без проблем.

 <?php // B.php ScopedInclude('C.php', array('includerFile' => __FILE__)); 

C.php может знать его включение, просматривая массив $ params.

 <?php // C.php echo $includerFile; 

Так что этот вопрос довольно старый, но я искал ответ и, оставив здесь неудовлетворенный, наткнулся на $_SERVER['SCRIPT_FILENAME']; Конечно, это работает, если файл php, делающий включение, является веб-страницей.

Это дает вам полный путь «включая файл» на сервере. например, /var/www/index.php. поэтому, если вы хотите просто имя файла, например index.php, вам нужно будет использовать basename (), например

basename($_SERVER['SCRIPT_FILENAME']);

Итак, если в вашем index.php у вас есть следующая строка:

<?php include("./somephp.php"); ?>

и в некоторыхphp.php у вас есть

echo "this is the file that included me: " . basename($_SERVER['SCRIPT_FILENAME']);

ты получишь

this is the file that included me: index.php

вывода в браузер. Это также работает, если пользователь обращается к вашему файлу без явного указания имени файла в URL-адресе, например www.example.com а не на www.example.com/index.php .

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

например

 <?php $g_including_files = array(); function my_include($file) { $bt = debug_backtrace(); global $g_including_files; $g_including_files[basename($file)] = $bt[0]['file']; return include($file); } 

Может быть, это полезно для вас 🙂

Решение

Зная, что функции, используемые для включения файлов, include , include_once , require и require_once , также зная, что они зарезервированные слова в PHP, что означает, что невозможно будет объявить пользовательские функции с тем же именем и на основе идеи wedgwood использовать debug_backtrace вы можете реально решить, из какого файла был вызван include.

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

 function GetIncludingFile() { $file = false; $backtrace = debug_backtrace(); $include_functions = array('include', 'include_once', 'require', 'require_once'); for ($index = 0; $index < count($backtrace); $index++) { $function = $backtrace[$index]['function']; if (in_array($function, $include_functions)) { $file = $backtrace[$index]['file']; break; } } return $file; } 

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

С помощью простой модификации вы также можете получить последний включенный файл:

 function GetIncludedFile() { $file = false; $backtrace = debug_backtrace(); $include_functions = array('include', 'include_once', 'require', 'require_once'); for ($index = 0; $index < count($backtrace); $index++) { $function = $backtrace[$index]['function']; if (in_array($function, $include_functions)) { $file = $backtrace[$index - 1]['file']; break; } } return $file; } 

наблюдения

Обратите внимание, что __FILE__ не является включенным файлом, а текущим файлом. Например:

файл A.php:

 <?php function callme() { echo __FILE__; } ?> 

файл B.php:

 <?php include('A.php'); callme(); ?> в <?php include('A.php'); callme(); ?> 

file index.php:

 <?php include('B.php'); ?> в <?php include('B.php'); ?> 

В приведенном выше примере в контексте файла B.php включен файл B.php (и включенный файл – index.php), но вывод функции callme – это путь A.php, потому что __FILE__ находится в A .php.


Также обратите внимание, что $_SERVER['SCRIPT_FILENAME'] предоставит абсолютный путь к скрипту, запрошенному клиентом. Если $_SERVER['SCRIPT_FILENAME'] == __FILE__ это означает, что текущий файл является запрошенным, и, следовательно, в нем, вероятно , не было никаких …

Вышеупомянутый метод проверяет, является ли текущий файл запрошенным, но не был ли он включен (ниже приведен пример того, как можно включить запрошенный файл). Фактическое решение проверить, не было ли каких-либо включений, может быть проверка count(get_included_files()) == 1 .


Запрошенный файл может быть включенным файлом следующим образом:

файл x.php

 <?php $var = 'something'; include('index.php'); ?> в <?php $var = 'something'; include('index.php'); ?> 

file index.php

 <?php if (!isset($var)) { include('x.php'); exit; } echo 'something'; ?> в <?php if (!isset($var)) { include('x.php'); exit; } echo 'something'; ?> 

В приведенном выше примере файл index.php будет включать в себя x.php, затем x.php будет включать index.php назад, впоследствии index.php выводит «что-то» и возвращает управление x.php, x.php возвращает управление индексу .php и достигает выхода;

Это показывает, что даже если index.php был запрошенным скриптом, он также был включен из другого сценария.