Check if a file was included or loaded

Php

Php Problem Overview


Is there any elegant way to check if a file was included by using include/include_once/require/require_once or if the page was actually loaded directly? I'm trying to set up a testing file inside class files while I'm creating them.

I'm looking for something similar to Python's if __name__ == "__main__": technique. Without setting globals or constants.

Php Solutions


Solution 1 - Php

Quoted from: https://stackoverflow.com/questions/4545878/how-to-know-if-php-script-is-called-via-require-once

> I was looking for a way to determine if a file have been included or called directly, all from within the file. At some point in my quest I passed through this thread. Checking various other threads on this and other sites and pages from the PHP manual I got enlightened and came up with this piece of code:

if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
  echo "called directly";
} else {
  echo "included/required";
}

> In essence it compares if the name of the current file (the one that > could be included) is the same as the file that is beeing executed.

Credit: @Interwebs Cowboy

Solution 2 - Php

you can do this by get_included_files — Returns an array with the names of included or required files and validate against __FILE__

Solution 3 - Php

I appreciate all the answers, but I didn't want to use any one's solution here, so I combined your ideas and got this:

<?php
    // place this at the top of the file
    if (count(get_included_files()) == 1) define ('TEST_SUITE', __FILE__);

    // now I can even include bootstrap which will include other
    // files with similar setups
    require_once '../bootstrap.php'

    // code ...
    class Bar {
        ...
    }
    // code ...

    if (defined('TEST_SUITE') && TEST_SUITE == __FILE__) {
        // run test suite here	
    }
?>

Solution 4 - Php

if (defined('FLAG_FROM_A_PARENT'))
// Works in all scenarios but I personally dislike this

if (__FILE__ == get_included_files()[0])
// Doesn't work with PHP prepend unless calling [1] instead.

if (__FILE__ == $_SERVER['SCRIPT_FILENAME'])
// May break on Windows due to mixed DIRECTORY_SEPARATOR

if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']))
// Doesn't work with files with the same basename but different paths

if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))
// Seems to do the trick as long as document root is properly configured

Note: On WAMP Servers virtual-hosts sometimes inherit the default document root setting, causing $_SERVER['DOCUMENT_ROOT'] to display wrong path.

Solution 5 - Php

<?php
    if (__FILE__ == $_SERVER['SCRIPT_FILENAME'])
    {
        //file was navigated to directly
    }
?>

Taken from mgutt's answer to a slightly different question here. It's important to note this doesn't work if the script is run from command line but other than that it functions exactly like python's

if __name__ == '__main__':

as far as I can tell

Solution 6 - Php

They is no way to separate them as include/include_once/require/require_once but php has get_included_files and get_required_files which is the same thing and only returns array of all included files. Its does not separate it if its required or included.

Example a.php

include 'b.php';
include_once 'c.php';
require 'd.php';
var_dump(get_required_files());

Output

array
  0 => string '..\lab\stockoverflow\a.php' (length=46) <---- Returns current file
  1 => string '..\lab\stockoverflow\b.php' (length=46)
  2 => string '..\lab\stockoverflow\c.php' (length=46)
  3 => string '..\lab\stockoverflow\d.php' (length=46)

But you can do something like

$inc = new IncludeManager($file);
var_dump($inc->find("b.php")); // Check if a file is included
var_dump($inc->getFiles("require_once")); // Get All  Required Once 

Class Used

class IncludeManager {
	private $list = array();
	private $tokens = array();
	private $find;
	private $file;
	private $type = array(262 => "include",261 => "include_once",259 => "reguire",258 => "require_once");

	function __construct($file) {
		$this->file = $file;
		$this->_parse();
	}

	private function _parse() {
		$tokens = token_get_all(file_get_contents($this->file));
		for($i = 0; $i < count($tokens); $i ++) {
			if (count($tokens[$i]) == 3) {
				if (array_key_exists($tokens[$i][0], $this->type)) {
					$f = $tokens[$i + 1][0] == 371 ? $tokens[$i + 2][1] : $tokens[$i + 1][1];
					$this->list[] = array("pos" => $i,"type" => $this->type[$tokens[$i][0]],"file" => trim($f, "\"\'"));
				}
			}
		}
	}

	public function find($find) {
		$finds = array_filter($this->list, function ($v) use($find) {
			return $v['file'] == $find;
		});
		
		return empty($finds) ? false : $finds;
	}

	public function getList() {
		return $this->list;
	}

	public function getFiles($type = null) {
		$finds = array_filter($this->list, function ($v) use($type) {
			return is_null($type) ? true : $type == $v['type'];
		});
		return empty($finds) ? false : $finds;
	}
}

Solution 7 - Php

get_included_files() return array where 0 index mean first "included" file. Because direct run mean "include" in this terms, you can simple check first index for equality for __FILE__:

if(get_included_files()[0] == __FILE__){
    do_stuff();
}

This can not work on PHP 4, because PHP 4 not add run file in this array.

Solution 8 - Php

Here's a different idea. Just include the file whenever you need it. Inside the include file you can decide whether it needs to include the contents:

<?php
if (defined("SOME_UNIQUE_IDENTIFIER_FOR_THIS_FILE"))
    return;
define("SOME_UNIQUE_IDENTIFIER_FOR_THIS_FILE", 1);

// Rest of code goes here

Solution 9 - Php

Working solution:

$target_file = '/home/path/folder/file.php'; // or use __FILE__

if ($x=function($e){return str_replace(array('\\'), '/', $e);}) if(in_array( $x($target_file), array_map( $x ,  get_included_files() ) ) )
{
	exit("Hello, already included !");
}

Solution 10 - Php

I don't think get_included_files is the perfect solution, what if your main script included some other scripts before the check? My suggestion is to check whether __FILE__ equals realpath($argv[1]):

<?php
require('phpunit/Autoload.php');

class MyTests extends PHPUnit_Framework_TestCase
{
	// blabla...
}

if (__FILE__ == realpath($argv[0])) {
	// run tests.
}

Solution 11 - Php

I took a similar approach to this issue when I cam across it. The solution I found was to load each file as needed in an include_once method. Hope this helps.

$FILES = get_included_files();  // Retrieves files included as array($FILE)
$FILE = __FILE__;               // Set value of current file with absolute path
if(!in_array($FILE, $FILES)){   // Checks if file $FILE is in $FILES
  include_once "PATH_TO_FILE";  // Includes file with include_once if $FILE is not found.
}

I have the following function established to check files loaded:

ARRAY_DUMP($FILES);

function ARRAY_DUMP($array){
  echo "
    <span style='font-size:12px;'>".date('h:i:s').":</span>
    <pre style='font-size:12px;'>", print_r($array, 1), "</pre>
  ";
}

Output:

currentArray
(
  [0] => /home/MY_DOMAIN/hardeen/index.php
  [1] => /home/MY_DOMAIN/hardeen/core/construct.php
  [2] => /home/MY_DOMAIN/hardeen/core/template.php
  [3] => /home/MY_DOMAIN/hardeen/bin/tags.php
  [4] => /home/MY_DOMAIN/hardeen/bin/systemFunction.php
)

Solution 12 - Php

It's sooo simple.. I have made something like this:

//code for file.php
if (!isset($file_included)){
   echo "It was loaded!";
} else {
  echo "It was included!";
}

//code for loader.php
//proves that atleast loader.php has loaded,
//not the file we targeted first..
$file_included = true;
include("../file.php");

And that's it.. as simple as in python.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionqwertymkView Question on Stackoverflow
Solution 1 - PhpJoshua KaiserView Answer on Stackoverflow
Solution 2 - PhpNullPoiиteяView Answer on Stackoverflow
Solution 3 - PhpqwertymkView Answer on Stackoverflow
Solution 4 - PhptimView Answer on Stackoverflow
Solution 5 - PhpJosh RView Answer on Stackoverflow
Solution 6 - PhpBabaView Answer on Stackoverflow
Solution 7 - PhpngmhView Answer on Stackoverflow
Solution 8 - Phpmuz the axeView Answer on Stackoverflow
Solution 9 - PhpT.ToduaView Answer on Stackoverflow
Solution 10 - PhpadamsmithView Answer on Stackoverflow
Solution 11 - PhpHardeenView Answer on Stackoverflow
Solution 12 - PhpstasinekView Answer on Stackoverflow