spl_autoload_register - 如何防止致命错误

时间:2013-07-29 18:17:28

标签: php class oop

我有以下功能来加载我的库:

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. ');
}

并自动加载:

function __construct() {

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

}

但不幸的例外并不能阻止我像没有课程或没有文件那样致命的错误。是否有一种优雅的方式来向用户显示我自己的沟通,而不是php错误?

1 个答案:

答案 0 :(得分:4)

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

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

因此,如果您的自动加载器无法加载该类,则必须执行任何操作。不抛出任何异常,不会触发错误。如果定义了PHP,你将调用另一个自动加载函数,如果没有,你将得到那个令人讨厌的“致命错误:类'Foobar \ InexistentClass'找不到”。这是一件好事,因为您使用的是无法加载的类 - 无论是因为拼写错误,还是自动加载器中的错误,还是其他原因。

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

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

最后建议:转到PSR-0 autoloading standard。现有很多自动装载机,它是任何体面库的事实标准。它将使everbodys的生活变得如此简单。

更新:

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