有没有办法找出哪个文件使用了require_once?

Posted

技术标签:

【中文标题】有没有办法找出哪个文件使用了require_once?【英文标题】:Is there a way to find out which FILE used require_once? 【发布时间】:2015-07-24 21:43:39 【问题描述】:

假设我有以下情况:

文件1.php

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

文件2.php:

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

init.php:

<?php
magic_function_which_tells_me_which_file_parsed_this_file();
...
?>

我知道这是一个远射,但是有没有办法从 init.php 中知道哪个文件在当前执行中包含了 init.php?

【问题讨论】:

你问是因为你想在不同的情况下包含不同的代码吗? 我认为“遗留代码”这句话说得够多了:)我知道使用了init文件,但在此之前我无法跟踪执行。 【参考方案1】:

即使没有函数,您也可以使用debug_backtrace 找到调用者:

test1.php

<?php
echo 'test1';
include 'test2.php';

test2.php

<?php
echo 'test2';
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
    )
)

无论如何,我不建议使用它,因为它过度使用会显着拖累性能。

【讨论】:

我没有看到我的 php 5.5 中缺少这些信息——你有关于它被删除的断言的参考吗?文档页面也没有提到这些信息被删除。 @ChrisBaker 对不起,我刚刚在文档上再次阅读了这个,显然我被误导了 - 提交我的答案太快了:\ 我的天啊,我现在感觉好傻,我故意忽略 debug_backtrace() 因为我认为它只适用于函数。 我添加了一个小实用函数来从回溯数据中解析这些信息,可能会有所帮助:)【参考方案2】:

在 init.php 的顶部,您可以使用debug_backtrace() 来获取有关堆栈的信息。这将告诉您,除其他外,哪个文件包含当前文件,以及在哪一行。

这是回溯输出的示例。如果你把它放在一个函数中,你将拥有另一层数据。如果您在文件本身中直接调用它,那么最顶层会告诉您哪个文件包含该文件。

array (size=2)
  0 => 
    array (size=3)
      'file' => string 'fileThatIncudedMe.php' (length=63)
      'line' => int 6
      'function' => string 'require_once' (length=12)

你可以把它包装成一个实用函数:

function whoIncludedThisFile() 
    $bt = debug_backtrace();
    $includedMe = false;
    while (count($bt) > 0) 
        $set = array_shift($bt);
        if (
            array_key_exists('function', $set) === true &&
            in_array($set['function'], array('require', 'require_once', 'include', 'include_once'))
        )
            $includedMe = array('file'=>$set['file'], 'line'=>$set['line']);
            break;
        
    
    return $includedMe;


print_r(whoIncludedThisFile());
// Array ( [file] => topLevelFile.php [line] => 2 )

【讨论】:

@ChrisBaker 你得到了我的投票,这将直接成为一个要点:P 这很好!如果 OP 接受mine 和你的答案之间的答案,我会赞成你的。【参考方案3】:

当然可以。带有debug_print_backtrace()

#0 require_once() 在 [C:\xampp\htdocs\file2.php:3] 调用

#1 require_once(C:\xampp\htdocs\file2.php) 在 [C:\xampp\htdocs\file1.php:3] 调用

这将告诉您init.php 包含在file2.php 在线3 中。

【讨论】:

【参考方案4】:

您也可以尝试使用变量来实现此目的。 让我们将其命名为 $parentFile:

$parentFile = basename(__FILE__);
require('some.file.here.php');

在 some.file.here.php 中:

if($parentFile == 'another.file.php')
    // do something;

【讨论】:

是的,在某些情况下这将是一个好方法,但在我的情况下,我不知道父文件,因为我正在处理非常旧的代码。【参考方案5】:

我会回答 - 显然所有功劳都归功于在我之前已经回答过这个问题的人。

我所做的是将 debug_backtrace 输出格式化为错误日志:

$debug = debug_backtrace(2 , 16);
error_log('-------------------------------' );
foreach ( $debug as $error ) 
     error_log( str_pad( $error['file' ], 120 ) . str_pad($error ['line'] , 8) . $error['function' ] );

结果将是每行一个文件,以表格的方式包含(文件、行、函数)。

【讨论】:

以上是关于有没有办法找出哪个文件使用了require_once?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法找出哪个表列导致与实体框架的转换出错?

有没有办法将 require_once() 的范围显式设置为全局?

找出在 UIActivityViewController 中单击了哪个图标

文件被哪个进程锁定?

有没有办法从另一个进程中找出完整的文件路径?

找出用户在iOS显示的UIAlertView上选择了哪个按钮的方法,请求允许应用程序接收推送通知