7

Let's say I have the following situation:

File1.php:

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

File2.php:

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

init.php:

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

I know this is a long-shot, but is there a way to know from within init.php which file included init.php it in the current execution?

iosifv
  • 1,153
  • 1
  • 10
  • 26
  • Are you asking because you want different code included for different situations? – Jonathan M May 13 '15 at 14:26
  • I think that the phrase "legacy code" says enough :) I know that the init file is used, but I can not trace the execution before that. – iosifv May 13 '15 at 14:38

5 Answers5

4

You are able to use debug_backtrace to find the caller even without functions:

test1.php

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

test2.php

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

Anyways, I'd not recommend using it because it can be a noticeable performance drag when used excessively.

Xatenev
  • 6,383
  • 3
  • 18
  • 42
  • 1
    I am not seeing the lack of this information in my php 5.5 -- do you have a reference on that assertion that it was removed? The documentation page also makes no mention of such information being removed. – Chris Baker May 13 '15 at 14:32
  • 1
    @ChrisBaker Sorry, I just read up on this again on the doc, and obviously i was misinformed - submitted my answer too fast :\ – Xatenev May 13 '15 at 14:33
  • OMG, I feel so stupid now, I intentionally disregarded debug_backtrace() because I thought that only works with functions. – iosifv May 13 '15 at 14:39
  • 1
    I added a little utility function to parse this info out of the backtrace data, might help :) – Chris Baker May 13 '15 at 14:43
3

At the top of init.php, you could use debug_backtrace() to get information about the stack. This will tell you, among other things, which file included the current file, and at what line.

This is a sample of the backtrace output. If you put this in a function, you'll have another layer of data. If you call it right in the file itself, then the top-most layer tells you what file included that one.

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

You could wrap this up into a utility function:

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 )
Chris Baker
  • 49,926
  • 12
  • 96
  • 115
  • @ChrisBaker you got my vote, this will go straight into a gist :P – Xatenev May 13 '15 at 14:45
  • This is nice! If OP were to accept an answer between [mine](http://stackoverflow.com/a/30217952/3000179) and yours, I'd favour yours. – ʰᵈˑ May 13 '15 at 15:25
3

Sure you can. With a debug_print_backtrace().

#0 require_once() called at [C:\xampp\htdocs\file2.php:3]

#1 require_once(C:\xampp\htdocs\file2.php) called at [C:\xampp\htdocs\file1.php:3]

This will tell you that init.php was included from file2.php on line 3.

ʰᵈˑ
  • 11,279
  • 3
  • 26
  • 49
0

You may also try to use a variable to achieve this. Let's name it $parentFile:

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

And in some.file.here.php:

if($parentFile == 'another.file.php')
    // do something;
Luki
  • 214
  • 1
  • 7
  • yes, it would be a good approach in some situations, but in my case I did not know the parent file because I was working on really old code. – iosifv May 13 '15 at 14:42
0

I will chip in with an answer - obviously all the credit goes to the guys that already answered this before me.

What I did was to format the debug_backtrace output to the error log:

$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' ] );
}

The result will be one file per line containing (file,line,function) in a table manner.

iosifv
  • 1,153
  • 1
  • 10
  • 26