Decision
Knowing that the functions used to include files are include
, include_once
, require
and require_once
, also knowing that they are reserved words in PHP, which means that it will not be possible to declare user-defined functions using the same name and based on the idea of wedgwood Using debug_backtrace
, you can really decide which file the include was called from.
What we are going to do is iterate over the return line until we find the most recent call to any of the four include functions and the file where it was called. The following code demonstrates the technique:
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; }
The above code will return the absolute path to the file in which the last inclusion occurred, if it was not included, it will return false. Please note that a file can be included from a file that was included from another file, the above function works only for the deepest inclusions.
With a simple modification, you can also get the last included file:
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; }
Observations
Note that __FILE__
not an included file, but the current file. For instance:
A.php file:
<?php function callme() { echo __FILE__; } ?>
B.php file:
<?php include('A.php'); callme(); ?>
file index.php:
<?php include('B.php'); ?>
In the example above, in the context of the B.php file, the B.php file is included (and the included file is index.php), but the output of the callme
function is the callme
path because __FILE__
is in A.php.
Also note that $_SERVER['SCRIPT_FILENAME']
will provide the absolute path to the script requested by the client. If $_SERVER['SCRIPT_FILENAME'] == __FILE__
means that the current file is requested, and therefore there probably were no inclusions ...
The above method checks if the current file is requested, but not if it was not included (below is an example of how to include the requested file). The actual solution for checking if there were any inclusions could be checking count(get_included_files()) == 1
.
The requested file may be an included file as follows:
file x.php
<?php $var = 'something'; include('index.php'); ?>
file index.php
<?php if (!isset($var)) { include('x.php'); exit; } echo 'something'; ?>
In the above example, the index.php file will include x.php, then x.php will include index.php back, subsequently index.php displays "something" and returns control x.php, x.php returns control to index.php and it reaches the exit;
This shows that even if index.php was the requested script, it was also included from another script.