【问题标题】:Having trouble using PHP's include statement使用 PHP 的 include 语句时遇到问题
【发布时间】:2020-01-27 06:21:25
【问题描述】:

我无法让 PHP 的“包含”语句在与使用“包含”语句的文件位于同一目录中的文件以外的任何文件上工作。当我尝试包含另一个目录中的任何文件时,整个应用程序都会中断并且没有任何加载。

我把那个脚本转储进去,说:

/var/www/html/fooA/testClass.php

并尝试使用:

/var/www/html/different_than_fooA/include_testClass.php

应用程序中断。但是,如果我包括:

/html/foo_1.php

在:

/html/foo_2.php

一切正常...

我保证这不是一个简单的语法问题,我已经尝试过尽可能多地编写它,在前面使用斜杠,或者在前面不使用斜杠,整个目录和部分目录,IP 地址,甚至尝试从其他服务器加载。我的猜测是它与 PHP 或 Apache 的配置方式有关。我可以在互联网上找到几乎没有关于这件事的任何内容,任何建议都会很棒。

<?php
    // THIS FILE IS TEST/TEST02.php

    require 'TEST01.php';
    $V = new X();
    $V->Z();
?>

【问题讨论】:

  • 您收到任何错误消息吗??
  • 页面只是不加载,只要我删除包含语句或将其更改为具有同一目录中的类的路径,页面就会加载
  • 这不是错误描述;启用错误报告或检查服务器的error_log
  • 您没有向我们展示有问题的代码或错误消息。我们所拥有的只是一些看似无关的类。修复隐形错误非常困难。请向我们展示必要的信息。谢谢
  • @AfterLife 如果你想回答这个问题,你不应该忽略我的建议......试试require_once() ...因为include() 函数的行为略有不同:php.net/manual/en/function.include.php

标签: php apache lamp


【解决方案1】:

您始终可以使用 PHP 的魔法常量,这样您就可以确定它会为您找出正确的路径。

/* lets say we have a folder structure like below
 *
 * - FolderA
 *  -- fileA.php
 * - FolderB
 *  -- fileB.php
 */

 // We require fileA.php in fileB.php, here is how we can do it

 require __DIR__.'/../FolderA/fileA.php';

这里是文档的链接。 https://www.php.net/manual/en/language.constants.predefined.php

【讨论】:

    【解决方案2】:

    默认情况下,PHP 设置include_path 如下:

    在 *nix 系统上

    include_path=".:/php/includes"
    

    在寡妇系统上

    include_path=".;c:\php\includes"
    

    您可以并且应该覆盖这些默认值以适应您的环境,因为您不太可能将所有相关文件都放在这些位置。

    使用 .在包含路径中允许相对包含,因为它意味着 当前目录。但是,显式使用会更有效 包括'./file'而不是让PHP总是检查当前目录 对于每个包含。

    为了覆盖默认位置,请使用 set_include_path("/path/to/includes/") 等,这样就可以通过简单的调用来包含如下文件:

    set_include_path("/path/to/includes/");
    include 'class.foobar.php';
    require 'functions.php'; // etc
    

    如果您需要加载类文件,另一种选择是使用 __autoload 等效方法并编写您自己的回调来处理文件加载。不推荐使用原始的 __autoload 方法,但存在改进的 spl_autoload 类来促进这一点。

    以下引用 ALIASED_SITE_ROOTROOT_PATH 在我的系统上是全局定义的常量并指向特定目录,因此与您无关,如果您决定采用这种方法加载类,则需要进行编辑。

    More info on "spl_autoload_register"

    function autoloader( $classname=false ){
    
        $included=get_included_files();
        $classname=rtrim( $classname, '.php' );
    
        $dirs = array(
            '/path/to/includes/',
            ALIASED_SITE_ROOT . '/inc/',
            ALIASED_SITE_ROOT . '/inc/forms/',
            ALIASED_SITE_ROOT . '/inc/lib/',
            ROOT_PATH . '/inc/',
            ROOT_PATH . '/'
        );
        /* add other locations to the above array */
        foreach( $dirs as $dir ) {
            $fullpath = $dir . $classname . '.php';
    
            if ( file_exists( $fullpath ) ) {
                if( !in_array( $fullpath, $included ) ) {
                    require_once( $fullpath );
                    clearstatcache();
                    break;
                }
            }
        }
        set_include_path( $dirs[ 0 ] );
    }
    spl_autoload_register( 'autoloader' );
    

    当您需要加载一个类时,在一个公共包含文件中注册了上述内容,当您需要使用该文件时,您不再需要执行require '/path/to/includes/foobar.php';,您可以简单地执行:

    $foo=new foobar(); // no need to use `require` or `include` as it has been autoloaded
    

    因此,以上内容适用于类 - 如果您采用这种方法,一致的命名策略将大有帮助!例如,我倾向于将上面显示的所有类定位为ALIASED_SITE_ROOT . '/inc/',并在自动加载函数中使用class.foobar.php的命名约定

    $fullpath = $dir . $classname . '.php';
    

    其实是

    $fullpath = $dir . 'class.' . $classname . '.php';
    

    因此类名必须与$classname给出的名称匹配,例如:

    class foobar{
        public function __construct(){
           /* etc */
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多