Есть ли элегантный способ проверить, был ли файл включен с помощью include
/ include_once
/ require
/ require_once
или если страница была загружена напрямую? Я пытаюсь настроить файл тестирования внутри файлов классов, пока я их создаю.
Я ищу что-то похожее на метод Python, if __name__ == "__main__":
Без установки глобальных или констант.
вы можете сделать это с помощью get_included_files. Возвращает массив с именами включенных или необходимых файлов и проверяет их на __FILE__
Я ценю все ответы, но я не хотел использовать какое-либо решение здесь, поэтому я объединил свои идеи и получил следующее:
<?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 } ?>
Цитата из: Как узнать, вызван ли скрипт php через require_once ()?
Я искал способ определить, был ли файл включен или вызван напрямую, все из файла. В какой-то момент в моих поисках я прошел через эту тему. Проверяя различные другие темы на этом и других сайтах и страницах из руководства PHP, я получил просвещение и придумал этот фрагмент кода:
if ( basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"]) ) { echo "called directly"; } else { echo "included/required" }
По сути, это сравнение, если имя текущего файла (тот, который может быть включен), совпадает с именем текущего файла.
Кредит: @Interwebs Cowboy
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['DOCUMENT_ROOT'] . $_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['DOCUMENT_ROOT'].$_SERVER['SCRIPT_NAME'])) // Seems to do the trick
Они не могут отделить их как include/include_once/require/require_once
но php имеет get_included_files
и get_required_files
что является одним и тем же, и возвращает массив всех включенных файлов. Его не отделяет, если это required
или included
.
Пример a.php
include 'b.php'; include_once 'c.php'; require 'd.php'; var_dump(get_required_files());
Вывод
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)
Но вы можете сделать что-то вроде
$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 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; } }
<?php if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) { //file was navigated to directly } ?>
Взято от ответа Муутта на несколько иной вопрос. Важно отметить, что это не сработает, если скрипт запущен из командной строки, но отличается от того, что он функционирует точно так же, как и python.
if __name__ == '__main__':
насколько я могу судить
Я не думаю, что get_included_files
– идеальное решение, что, если ваш основной скрипт включал некоторые другие скрипты перед проверкой? Мое предложение – проверить, равен ли __FILE__
realpath($argv[1])
:
<?php require('phpunit/Autoload.php'); class MyTests extends PHPUnit_Framework_TestCase { // blabla... } if (__FILE__ == realpath($argv[0])) { // run tests. }
Я применил подобный подход к этому вопросу, когда я поглядел на него. Решение, которое я нашел, это загрузить каждый файл по мере необходимости в методе include_once. Надеюсь это поможет.
$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. }
У меня установлена следующая функция для проверки загруженных файлов:
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> "; }
Вывод:
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 )
Это просто. Я сделал что-то вроде этого:
//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");
И это все .. так же просто, как в python.
if(get_included_files()[0] == __FILE__){ do_stuff(); }