PHP中的包含路径和__autoload函数

3

我正在尝试将几个php脚本转换为使用__autoload函数。目前,我可以像这样使用include和require函数:

require_once('path/to/script.php');

但是在__autoload函数内,我无法使用上面的代码。我必须使用以下代码:

require_once('absolute/path/to/script.php');

为什么似乎__autoload函数没有使用我在php.ini中指定的include路径?

从技术上讲,这不是对你问题的回答,但你可能会发现它有用,所以我会把它作为评论放在这里:既然你所有的包含文件都通过autoload进行了处理,那么还有必要使用php.ini中的include路径吗?你可以只需将包含文件夹相对于包含autoload函数的文件定义即可。例如,如果文件位于根目录,而包含文件位于/include/中,则只需在autoload内部添加“include/”即可。 - Rupert Madden-Abbott
请提供 echo get_include_path(); 的输出结果好吗?唯一我能想到的情况是您的包含路径中没有 . - NikiC
@nikic:我使用那个echo语句进行检查,同时也查看了php.ini文件本身。 - cskwrd
4个回答

10
不要使用__autoload... 它有一些缺点(包括限制每次执行只能使用一个)。如果你使用的是5.2+版本,请使用spl_autoload_register代替。
所以我通常的做法是,创建一个类:
class AutoLoader {
    protected static $paths = array(
        PATH_TO_LIBRARIES,
    );
    public static function addPath($path) {
        $path = realpath($path);
        if ($path) {
            self::$paths[] = $path;
        }
    }
    public static function load($class) {
        $classPath = $class; // Do whatever logic here
        foreach (self::$paths as $path) {
            if (is_file($path . $classPath)) {
                require_once $path . $classPath;
                return;
            }
        }
    }
}
spl_autoload_register(array('AutoLoader', 'load'));

那样,如果你添加一个库集,你可以通过调用AutoLoader::AddPath($path);将其“添加”到你的路径中。这样做可以使得使用你的自动加载器进行测试变得更加容易(在我看来)。
还有一点需要注意的是,除非绝对必要,不要从自动加载类中抛出异常。原因是你可以安装多个自动加载器,所以如果你不知道如何加载文件,可能存在另一个加载器来加载它。但是如果你抛出异常,它将跳过其他加载器...
就个人而言,我从不喜欢在包含文件时使用相对路径。特别是在有多个包含目录(如pear)的情况下,当你看到require 'foo/bar.php';时,很难知道到底导入了哪个文件。我更喜欢在文件集的开头定义绝对路径define('PATH_ROOT', dirname(__FILE__));,然后在该目录下定义所有其他有用的路径(PATH_LIBRARIESPATH_TEMPLATES等)。这样,一切都被绝对定义...不需要处理相对路径(就像你现在遇到的问题)...

0

没有看到整个设置,不确定。我的自动加载函数在全局函数文件中,看起来像这样:

function __autoload($class) {
    if (file_exists("includes/{$class}.php")) {
        require_once("includes/{$class}.php");
    }
    /**
     * Add any additional directories to search in within an else if statement here
     */
    else {
        // handle error gracefully
    }
}

我使用相对路径,因为脚本包含在我的index.php文件中,所有HTTP请求都通过它传递。


似乎你的回答被某种原因截断了。"because"之后的部分丢失了。 - NikiC
谢谢!不知道发生了什么。 - Martin Bean

0

似乎您的包含路径中没有.,请使用以下代码添加:

set_include_path('.' . PATH_SEPARATOR . get_include_path());

现在PHP也应该相对于执行脚本的目录进行查找了。 (这里执行的脚本类似于index.php,而不是autoload.php

但是为什么不直接使用普通的相对路径,例如./path/to/class.php呢?


路径中已经包含了 .. 是相对于当前文件的工作目录(换句话说,它等同于 dirname(__FILE__))... 这就是为什么它在一个文件中可以正常工作,而在另一个文件中却不行(因为它们之间的相对工作目录发生了变化)... - ircmaxell
@ircmaxell:你真的很确定你所说的是正确的吗?我有这样的经验,PHP将目录视为cwd,因此最初执行脚本所在的位置不在包含文件的位置。更多信息(虽然是德语)和我的路径解析类。(解析类还不完美,但已经很好了。) - NikiC

0

我怀疑您的__autoload()函数在调用它的代码所在的文件中是分开的。包含文件的路径将相对于声明__autoload()函数的文件。


我也曾这样想,但是我使用了php.ini文件中的“auto_prepend_file”设置,并将包含__autoload函数的文件放置在所有相对路径开始的文件夹中,但仍然无法正常工作。 - cskwrd
-1 因为我认为这个答案是错误的(如果我错了,请纠正我):据我所知,文件相对于执行脚本包括。也就是说,如果调用了index.php,但是autoload位于foo/bar/autoload.php中,路径仍然会相对于index.php解析。当尝试所有include_paths后,PHP最后才回退到foo/bar。 - NikiC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接