2

I have the following function to load my libraries:

function load_class($name) {
    $namePath = explode('_', $name);
    $filePath = '';
    if (is_array($namePath)) {
        for ($i=0; $i<sizeof($namePath); $i++) {
            $filePath .= $namePath[$i];
            if ($i != sizeof($namePath) - 1) $filePath .= '/';
        }
    } else $filePath = $name;
    if (is_file($filePath . '.php')) require_once($filePath . '.php'); 
    else if (is_file($filePath . '.class.php')) require_once($filePath . '.class.php');
    else throw new Exception('Unable to load class: ' . $name . '. No such file or a directory. ');
    if (!class_exists($name)) throw new Exception('Class: ' . $name . ' doesn\'t exists. ');
}

And autoload:

function __construct() {

    try {
        spl_autoload_register(array($this, 'load_class')); 
    } catch (Exception $e) {
        echo $e -> getMessage();
    }

}

But unfortunatelly exceptions doesn't prevent me from getting fatal errors like there is no class or there is no file. Is there an elegant way to just show user my own communicate, not the php error?

4

1 回答 1

5

一件事: spl_autoload_register 不会抛出异常。所以根本没有必要将该调用包装到 try/catch 中——它不会发生任何事情!它唯一返回的是一个布尔值:成功时为 true,失败时为 false,这可能仅在您尝试注册不存在的函数或传递不可调用的函数时才会发生。

第二件事:做一个好公民,不要在你自己的函数中取消自动加载过程!如果您或其他任何人将您的自动加载器与第二个自动加载器一起使用,就像正在使用任何其他带有它自己的自动加载器的库一样,那么所有这些自动加载器都可能被类名调用,并且只有负责的那个类必须加载它。

因此,如果您的自动加载器无法加载该类,它必须什么也不做。不抛出任何异常,不触发错误。如果定义了另一个自动加载函数,PHP 将在你的之后调用另一个自动加载函数,如果没有,你会得到那个讨厌的“致命错误:找不到类 'Foobar\InexistentClass'”。这是一件好事,因为您正在使用一个无法加载的类——要么是因为拼写错误,要么是自动加载器中的错误,要么是其他原因。

还有一件事:你真的不必使用require_once()加载。自动加载器只会被触发一次来加载一个类。require_once()有性能损失,因为 PHP 必须检查文件之前是否已加载 - 此检查将永远不会阻止第二次加载,因为自动加载器永远不会被第二次调用已知类。

如果无法加载类,如何防止致命错误?不可能的!从理论上讲,自动加载器可以被编码为运行eval()tp 创建所需的类作为没有任何函数的空代码片段,或者甚至可以使用指定的 __set、__get 和 __call 魔术函数来拦截任何使用,但这有什么帮助?您的代码需要一个可以做某事的类,但找不到该类!这确实是一个致命错误,应该解决,而不是隐藏。

最后的建议:使用PSR-0 自动加载标准。已经有很多自动加载器存在,它是任何体面库的事实上的标准。这将使每个人的生活变得更加轻松。

更新:

您可以安装自己的错误处理程序,在 PHP 错误上执行:set_error_handler()但这对致命错误没有帮助。

于 2013-07-29T19:12:19.030 回答