我有以下函数来加载我的库:
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. ');
}
Run Code Online (Sandbox Code Playgroud)
并自动加载:
function __construct() {
try {
spl_autoload_register(array($this, 'load_class'));
} catch (Exception $e) {
echo $e -> getMessage();
}
}
Run Code Online (Sandbox Code Playgroud)
但不幸的是,异常并不能阻止我遇到致命错误,例如没有类或没有文件。有没有一种优雅的方法来向用户显示我自己的通信,而不是 php 错误?
一件事: 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()但这对解决致命错误没有帮助。