doujiao1538 2013-07-29 18:17
浏览 74
已采纳

spl_autoload_register - 如何防止致命错误

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?

  • 写回答

1条回答 默认 最新

  • dongtao5055 2013-07-29 19:12
    关注

    One thing: spl_autoload_register does not throw exceptions. So there simply is no need to wrap that call into a try/catch - it won't ever happen to do anything! The only thing it returns is a boolean: true on success, or false on failure, which will probably only happen if you try to register a function that does not exist, or you pass something that is not callable.

    The second thing: Be a nice citizen, do not cancel the autoloading process in your own function! Should you or anyone else use your autoloader together with a second one, like it would be the case if any other library with it's own autoloader is in use, then ALL these autoloaders might get called with the classname, and ONLY the one responsible for that kind of class must load it.

    So if your autoloader cannot load the class, it must do nothing. Not throw any exception, not trigger an error. PHP will call another autoloading function after yours if it is defined, and if not, you'll get that nasty "Fatal error: Class 'Foobar\InexistentClass' not found". And this is a good thing because you were using a class that couldn't be loaded - either because of a typo, or an error in the autoloader, or some other reason.

    One more thing: You really don't have to use require_once() for the loading. The autoloader will only be triggered ONCE to load a class. require_once() has a performance penalty because PHP must check if the file has been loaded before - and this check will NEVER prevent a second loading, because the autoloader will never be called a second time for an already known class.

    How to prevent fatal errors if classes cannot be loaded? Impossible! In theory the autoloader could be coded to run eval() tp create the required class as an empty code fragment without any functions, or maybe even with designated __set, __get and __call magic functions that would intercept any usage, but what would that help? Your code required a class that does something, and that class cannot be found! This really IS a fatal error, and should be resolved, not hidden.

    Last suggestion: Go with the PSR-0 autoloading standard. There are plenty of autoloaders already existing, and it is the defacto standard for any decent library. It will make everbodys life so much easier.

    Update:

    You can install your own error handler that is executed on PHP errors: set_error_handler() But this won't help with fatal errors.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题