2013-07-29 113 views
2

我有以下函数加载我的图书馆:spl_autoload_register - 如何防止致命错误

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错误?

+0

http://stackoverflow.com/questions/277224/how-do-i-catch-a-php-fatal-error – Bart

回答

4

有一件事:spl_autoload_register不会抛出异常。所以根本就不需要将这个调用包装成一个try/catch - 它不会发生任何事情!它返回的唯一的事情是一个布尔值:真正的成功,或FALSE的失败,如果您尝试注册一个不存在的功能,否则你传的东西是不是调用,这将很可能只发生。

第二件事:做一个好公民,不要在自己的功能中取消自动加载过程!如果你或其他任何人的第二个一起使用磁带自动加载机,喜欢的话会出现这种情况,如果与它自己的自动加载任何其他库正在使用中,那么所有这些磁带自动加载机可能会被调用的类名,只有一个负责该类的类必须加载它。

因此,如果您的自动加载器无法加载该类,则它无法执行任何操作。不抛出任何异常,不会触发错误。 PHP会后你调用另一个自动加载功能,如果它被定义,如果没有,你会得到那个讨厌的“致命错误:类‘Foobar的\ InexistentClass’未找到”。这是一件好事,因为您使用的是无法加载的类 - 无论是由于拼写错误还是自动加载器中的错误或其他原因。

还有一件事:你真的不必使用require_once()加载。自动加载器只会触发一次加载一个类。 require_once()有性能损失,因为PHP必须检查文件是否已被前装 - 这支票不会妨碍第二加载,因为自动加载磁带机将永远不会被调用的已知类第二次。

如何防止致命错误,如果类不能被加载?不可能!从理论上来说,自动加载机可编码运行eval() TP创建所需类为空的代码片段,没有任何功能,甚至可能与指定__set,__get和__call魔术函数会截取任意使用,但会是什么帮助?你的代码需要一个能够做某事的类,而这个类不能被发现!这真的是一个致命的错误,应该解决,而不是隐藏。

最后的建议:去PSR-0 autoloading standard。现在已经有很多自动加载器了,它是任何体面的图书馆的事实标准。它将使everbodys的生活变得如此简单。

更新:

您可以安装上PHP错误执行自己的错误处理:set_error_handler()但这不会致命错误帮助。