Подтвердить что ты не робот

Проверьте, был ли файл включен или загружен

Есть ли элегантный способ проверить, был ли файл включен с помощью include/include_once/require/require_once, или если страница была загружена напрямую? Я пытаюсь настроить файл тестирования внутри файлов класса, пока я их создаю.

Я ищу что-то похожее на технику Python if __name__ == "__main__":. Без установки глобальных или констант.

4b9b3361

Ответ 1

Цитата из: Как узнать, вызвана ли php script через require_once()?

Я искал способ определить, был ли файл включен или вызван напрямую, все из файла. В какой-то момент в моих поисках я прошел через эту тему. Проверяя различные другие темы на этом и других сайтах и ​​страницах из руководства PHP, я проснулся и придумал этот фрагмент кода:

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


else {   echo "included/required" }

В сущности, он сравнивает, если имя текущего файла (тот, который может быть включен) совпадает с файлом, который выполняется.

Кредит: Ковбой @Interwebs

Ответ 2

вы можете сделать это с помощью get_included_files - возвращает массив с именами включенных или требуемых файлов и проверяет на __FILE__

Ответ 3

Я ценю все ответы, но я не хотел использовать какое-либо решение здесь, поэтому я объединил свои идеи и получил следующее:

<?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  
    }
?>

Ответ 4

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 as long as the file is under the document root.

Примечание. На серверах WAMP виртуальные хосты иногда наследуют корневую настройку документа по умолчанию, в результате чего $_SERVER['DOCUMENT_ROOT'] отображает неверный путь.

Ответ 5

Они не могут отделить их как 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;
    }
}

Ответ 6

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

Взято из mgutt ответ на несколько иной вопрос здесь. Важно отметить, что это не работает, если script запускается из командной строки, но отличается от того, что он функционирует точно так же, как python

if __name__ == '__main__':

насколько я могу судить

Ответ 7

get_included_files() возвращает массив, где индекс 0 означает первый "включенный" файл. Поскольку прямой пробег означает "включить" в этих терминах, вы можете просто проверить первый индекс для равенства для __FILE__:

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

Это не может работать на PHP 4, потому что PHP 4 не добавляет файл запуска в этот массив.

Ответ 8

Рабочее решение:

$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 !");
}

Ответ 9

Я не думаю, что get_included_files является идеальным решением, а что, если ваш основной script включил некоторые другие скрипты перед проверкой? Мое предложение - проверить, равен ли __FILE__ realpath($argv[1]):

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

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

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

Ответ 10

Я применил подобный подход к этой проблеме, когда я кулаком по ней. Решение, которое я нашел, это загрузить каждый файл по мере необходимости в методе 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
)

Ответ 11

Здесь другая идея. Просто укажите файл, когда вам это нужно. Внутри файла include вы можете решить, нужно ли включать содержимое:

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

// Rest of code goes here

Ответ 12

Это ооочень просто.. Я сделал что-то вроде этого:

//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.