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

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

Я знаю, что есть __FILE__ магическая константа, но это не помогает, так как она возвращает имя входит, а не в том числе один.

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

4 ответов


это на самом деле просто частный случай того, что делают движки шаблонов 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.РНР. поэтому, если вы хотите только имя файла, например index.php, вам нужно будет использовать basename () например

basename($_SERVER['SCRIPT_FILENAME']);

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

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

и в somephp.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, include_once, require и require_once, также зная, что они зарезервированы в PHP, это означает, что невозможно будет объявить пользовательские функции с тем же именем и на основе Веджвуд!--22--> С помощью debug_backtrace вы можете на самом деле выяснить, из какого файла был вызван 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. Обратите внимание, что файл может быть включен из файла, который был включен из другого файла, вышеуказанная функция работает только для самого глубокого include.

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

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();
?>

файл index.на 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');
?>

файл index.в PHP

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

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

это показывает, что даже если индекс.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);                                                                                                                                                                     
    } 

может быть, это будет полезно для вас:)