【问题标题】:Check if a file was included or loaded检查文件是否包含或加载
【发布时间】:2012-10-11 13:37:44
【问题描述】:

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

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

【问题讨论】:

  • 觉得已经找到方法了....等一下
  • 这个问题有点含糊。如果您想知道是否已经加载了 不同 文件(来自当前文件):if(in_array(__DIR__ . '/path/to/file.php', get_included_files())){ echo __DIR__ . '/path/to/file.php was already loaded'; }

标签: php


【解决方案1】:
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

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

【讨论】:

    【解决方案2】:

    引用自:How to know if php script is called via require_once()?

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

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

    本质上,它比较当前文件的名称(即 可以包含)与正在执行的文件相同。

    图片来源:@Interwebs Cowboy

    【讨论】:

    • 我认为当两个文件具有相同的名称但位于不同的目录中时,这会中断。没有basename() 也能正常工作。例如,如果/var/www/index.php 包含/var/www/test/index.php/var/www/test/index.php 会认为它被直接调用。不过,+1 因为这对我有很大帮助:)
    • 当文件被 cron 作业调用时它不起作用,因为你没有 $_SERVER 变量...
    • 只投票否决,因为 NullPoiиteя 的答案更好,应该被 IMO 接受。
    【解决方案3】:

    get_included_files() 返回数组,其中 0 索引表示第一个“包含”文件。因为直接运行在这个术语中意味着“包含”,所以您可以简单地检查__FILE__ 的第一个索引是否相等:

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

    这不适用于 PHP 4,因为 PHP 4 没有在这个数组中添加运行文件。

    【讨论】:

    • 虽然这可以解决问题,但不鼓励在 SO 上仅使用代码回答。最好解释一下为什么这会解决问题。
    • 请看How to Answer
    • 您的答案应该解释这如何解决问题,以及如何改进提供相同解决方案的现有投票答案。此外,由于这个问题已有 5 年历史,并且有很多赞成的答案,因此最近有未回答问题的用户会更加感谢您的努力。
    • 尽管有负面的 cmets,但我发现这是问题的最佳答案(不假设 Web 服务器,不会不必要地循环,简单等)。感谢 Enyby 和 ngmh。
    【解决方案4】:

    工作解决方案:

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

    【讨论】:

      【解决方案5】:

      这是一个不同的想法。 只需在需要时包含该文件。 在包含文件中,您可以决定是否需要包含内容:

      <?php
      if (defined("SOME_UNIQUE_IDENTIFIER_FOR_THIS_FILE"))
          return;
      define("SOME_UNIQUE_IDENTIFIER_FOR_THIS_FILE", 1);
      
      // Rest of code goes here
      

      【讨论】:

      【解决方案6】:

      太简单了.. 我做了这样的事情:

      //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 中一样简单。

      【讨论】:

        【解决方案7】:

        当我遇到这个问题时,我采取了类似的方法。我找到的解决方案是在 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
        )
        

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

            【解决方案9】:
            <?php
                if (__FILE__ == $_SERVER['SCRIPT_FILENAME'])
                {
                    //file was navigated to directly
                }
            ?>
            

            取自 mgutt 对略有不同的问题 here 的回答。重要的是要注意,如果脚本是从命令行运行的,这不起作用,但除此之外它的功能与 python 的

            if __name__ == '__main__':
            

            据我所知

            【讨论】:

              【解决方案10】:

              您可以通过 get_included_files 执行此操作 — 返回包含包含或所需文件名称的数组,并根据 __FILE__ 进行验证

              【讨论】:

              • 我将如何检查我已加载的内容? /test.php 可以包含/includes/test.php
              • 此处的完整示例:stackoverflow.com/a/52467334/2377343
              • 对我不起作用。正如 get_included_files 上的文档所说:最初调用的脚本被认为是“包含文件”,因此它将与 include 和 family 引用的文件一起列出。
              【解决方案11】:

              我不认为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.
              }
              

              【讨论】:

                【解决方案12】:

                它们无法将它们分隔为include/include_once/require/require_once,但 php 具有 get_included_filesget_required_files,它们是相同的,并且只返回所有包含文件的数组。如果它的requiredincluded,它不会将它分开。

                例如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;
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 2011-01-24
                  • 1970-01-01
                  • 2018-01-15
                  • 1970-01-01
                  • 2012-01-14
                  • 2011-05-04
                  • 1970-01-01
                  • 2012-02-21
                  • 2011-10-28
                  相关资源
                  最近更新 更多