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 phython如何实现以下功能?查找同一用户名的消费金额合并—
  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿速度
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址