Может ли встроенный 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.