简体   繁体   English

包含的PHP文件可以知道它包含在哪里吗?

[英]Can an included PHP file know where it was included from?

For example, 例如,

This is index.php 这是index.php

<?
require_once('header.php');
?>

Can header.php know it was included by index.php? header.php能知道它被index.php包含了吗?

--EDIT-- - 编辑 -

I found a solution: 我找到了解决方案:

function backtrace_filename_includes($name){
    $backtrace_array=debug_backtrace();
    if (strpos($backtrace_array[1]['file'],$name)==false){
        return false;
    }else{
        return true;
    }
}

header.php header.php文件

<?
if (backtrace_filename_includes('index.php')) echo "index.php";
?>

While $_SERVER['PHP_SELF'] will contain the currently executing script, there is no way to determine from an included file which specific script caused the include. 虽然$_SERVER['PHP_SELF']将包含当前正在执行的脚本,但是无法从包含的文件中确定哪个特定脚本导致了包含。

This means that if a.php includes b.php , which includes c.php , c.php will have no way of knowing that b.php was the includer. 这意味着如果a.php包含b.php ,其中包括c.php ,则c.php将无法知道b.php是包含者。 The best you can get is that a.php is the currently executing script. 你能得到的最好的是a.php是当前正在执行的脚本。


Edit: Yup, my above answer is technically wrong -- you can use debug_backtrace to find the caller, even without functions, up until PHP 5.4, which removes this functionality . 编辑:是的,我的上述答案在技术上是错误的 - 你可以使用debug_backtrace找到调用者,即使没有函数, 直到PHP 5.4,这将删除此功能

a.php: a.php只会:

<?php
echo 'A';
include 'b.php';

b.php: b.php:

<?php
echo 'B';
include 'c.php';

c.php: c.php:

<?php
echo 'C';
print_r(debug_backtrace());

Output: 输出:

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
        )

)

So while this works, you probably shouldn't use it. 因此,虽然这有效,但您可能不应该使用它。 debug_backtrace can be a noticeable performance drag when used excessively. 当过度使用时, debug_backtrace可能会引起明显的性能拖累。

get_included_files() provides a stack of the files included, in the order they are included, which in my case gave me everything I needed. get_included_files()提供了包含文件的堆栈,按照它们包含的顺序,在我的例子中给了我所需的一切。

Specifically, if you call get_included_files() within a file that has been included, that file's own file-path will be the most recent entry on the stack returned by get_included_files() , the one that included it is above that, etc. 具体来说,如果在已包含的文件中调用get_included_files() ,则该文件自己的文件路径将是get_included_files()返回的堆栈上的最新条目,包含它的那个条目高于该条目,等等。

The caveat is that files are only listed once, so if the same file is included more than once, only the first include will show up in the stack. 需要注意的是,文件只列出一次,因此如果同一文件被包含多次,则只有第一个包含将显示在堆栈中。 For my purposes that wasn't an issue, but it definitely means this won't work in all cases. 对于我的目的而言,这不是一个问题,但它绝对意味着这在所有情况下都不起作用。

Specific example: imagine the file 'test1.php' includes 'test_include.php'. 具体示例:假设文件'test1.php'包含'test_include.php'。 The result of get_included_files() from the perspective of 'test_include.php' after loading test1.php in the browser are as follows (given, as you can see, that I've got an auto_prepend file, which in turn loads an autoloader). 在浏览器中加载test1.php后,从'test_include.php'的角度看get_included_files()的结果如下(给出,我看到,我有一个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"
}

So test_include.php only has to do a little array_pop'ing to figure out who included it. 所以test_include.php只需要做一些array_pop'ing就可以找出包含它的人。

PHP tracks the file that does the including for you in the backtrace. PHP跟踪在回溯中为您执行包含的文件。 With a little helper function you can get the filename that had the last include command: 使用一个小帮助函数,您可以获得具有最后一个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.');
}

Usage: 用法:

main.php: main.php:

<?php
include('sub.php');

sub.php: sub.php:

<?php
echo basename(include_by()); # main.php

See as well a related usage of the backtrace: Caller function in PHP 5? 请参阅回溯的相关用法: PHP 5中的调用函数? .

$_SERVER['PHP_SELF'] should still point to file originally accessed, or you could set a variable before the require, eg: $_SERVER['PHP_SELF']仍应指向最初访问过的文件,或者您可以在require之前设置变量,例如:

$section = 'home';
require_once('header.php');

... ...

if ($section == 'home') {
    ...
}
debug_print_backtrace();

检查PHP文档

Easiest way in the web server environment: $_SERVER['SCRIPT_FILENAME'] will show the original file that is called. Web服务器环境中最简单的方法: $_SERVER['SCRIPT_FILENAME']将显示被调用的原始文件。

Universal way - debug_backtrace() will show you all previous steps of the execution, which will include calls to require/include functions. 通用方式 - debug_backtrace()将显示执行的所有先前步骤,其中包括对require / include函数的调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM