检查是否包含或加载了文件

qwe*_*ymk 40 php

是否有任何优雅的方法来检查文件是否包含使用include/ include_once/ require/ require_once或者页面是否实际直接加载?我正在尝试在创建它们时在类文件中设置测试文件.

我正在寻找类似于Python if __name__ == "__main__":技术的东西.不设置全局变量或常量.

Nul*_*teя 25

你可以通过get_included_files来做到这一点 - 返回一个包含所包含或必需文件名称的数组并进行验证__FILE__


Jos*_*ser 20

引自:如何知道是否通过require_once()调用php脚本?

我正在寻找一种方法来确定文件是否已被包含或直接调用,所有这些都来自文件.在我的任务的某个时刻,我通过了这个线程.检查PHP手册中这个和其他网站和页面上的各种其他线程我得到了启发,并提出了这段代码:

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

实质上,它会比较当前文件的名称(可以包含的文件的名称)是否与正在执行的文件相同.

图片来源:@Interwebs Cowboy

  • 我认为当两个文件具有相同的名称但位于不同的目录中时会中断.没有`basename()`工作正常.例如,如果`/ var/www/index.php`包含`/ var/www/test/index.php`,`/ var/www/test/index.php`会认为它是直接调用的.仍然,+1因为这帮助了我很多:) (3认同)

qwe*_*ymk 16

我很欣赏所有答案,但我不想在这里使用任何一个解决方案,所以我结合了你的想法并得到了这个:

<?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  
    }
?>
Run Code Online (Sandbox Code Playgroud)


tim*_*tim 8

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.
Run Code Online (Sandbox Code Playgroud)

注意:在WAMP服务器上,虚拟主机有时会继承默认文档根设置,导致$ _SERVER ['DOCUMENT_ROOT']显示错误的路径.


Bab*_*aba 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());
Run Code Online (Sandbox Code Playgroud)

产量

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)
Run Code Online (Sandbox Code Playgroud)

但你可以做点什么

$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 
Run Code Online (Sandbox Code Playgroud)

使用的类

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Jos*_*h R 5

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

摘自 mgutt 对这里稍微不同的问题的回答。重要的是要注意,如果脚本是从命令行运行的,这将不起作用,但除此之外它的功能与 python 完全一样

if __name__ == '__main__':
Run Code Online (Sandbox Code Playgroud)

据我所知


ngm*_*gmh 5

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();
}
Run Code Online (Sandbox Code Playgroud)

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

  • 虽然这可能会解决问题,但不鼓励在 SO 上仅提供代码答案。最好解释一下为什么这会解决问题。 (2认同)