最模板 - 外贸网站建设,外贸网站模板

最模板

当前位置: 首页 > Magento > Magento教程 >

PHP的错误处理和Magento开发者模式

时间:2014-06-02 07:35来源:未知 作者:最模板zuimoban 点击:
在PHP中针对错误的配置有如下 1 2 3 4 log_errors display_errors error_log error_reporting error_reporting设置了报告的类型,log_errors决定了是否记录错误,记录的地方由error_log指定,display_errors决定是否显示错

在PHP中针对错误的配置有如下

1
2
3
4
log_errors
display_errors
error_log
error_reporting

error_reporting设置了报告的类型,log_errors决定了是否记录错误,记录的地方由error_log指定,display_errors决定是否显示错误信息。

如果你曾经使用过PHP的try语句,或者你会有疑问,错误和异常有何不一样?

简单来说,try块中的代码如果有抛出异常,可以被catch截获。但是发生错误还是会发送给PHP的错误处理程序。比如如下这段程序:

1
2
3
4
5
6
7
8
9
10
11
12
function doSomeThing($var){
    throw new Exception("Please stop hitting me");
 
}
 
try{
    $f = file("/www/test.txt");
    $a = 10/0;
    doSomeThing($a);
}catch(Exception $e){
    echo "----->Exception";
}

这里面同时发生了PHP错误和抛出异常。PHP错误可能会记录到错误日志,而异常被catch捕获进行处理。(注意,如果发生比较严重的错误,比如语法错误,PHP直接中断解析,后面的方法不会被执行,也就不会有异常抛出了),PHP错误的处理默认是有PHP本身的默认程序处理的,不过可以使用set_error_handler方法来设置一个自定义的错误处理方法。

关于PHP的错误处理,可以参考:

http://cn2.php.net/manual/zh/errorfunc.configuration.php

http://cn2.php.net/manual/zh/errorfunc.constants.php


http://cn2.php.net/manual/zh/function.set-error-handler.php

由于我们将使用set_error_handler函数设置一个自定义错误处理程序来替代PHP标准的错误处理程序,所以对这个函数用法必须来个彻底认识。

1
mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )

$error_handler设置回调函数,这个函数设置是有要求的,具体内容可参阅PHP文档,注意这个回调函数如果返回了false,则PHP的标准错误处理程序继续运行。我们看文档中的关于这个函数的描述:

“ 本函数可以用你自己定义的方式来处理运行中的错误, 例如,在应用程序中严重错误发生时,或者在特定条件下触发了一个错误(使用 trigger_error()),你需要对数据/文件做清理回收。

重要的是要记住 error_types 里指定的错误类型都会绕过 PHP 标准错误处理程序(默认是E_ALL | E_STRICT,就是全部错误类型都有自定义函数处理,否则没有包含的由PHP标准程序处理), 除非回调函数返回了 FALSE。 error_reporting() 设置将不会起到作用而你的错误处理函数继续会被调用 —— 不过你仍然可以获取 error_reporting 的当前值,并做适当处理(这里说的是error_reporting设置是针对标准错误处理程序的,它对自定义的错误处理程序无效)。 需要特别注意的是带 @ error-control operator 前缀的语句发生错误时,这个值会是 0(PHP中可以使用@前缀来强制一个语句不报告错误,实际的实现是把error_reporting设置为0,那么标准错误处理程序就不会处理错误,但是这个情况在使用了自定义错误处理程序时无效,有些错误自定义处理程序是无法处理的,实际上有些错误先于自定义错误处理程序前触发,它实际还是使用标准处理程序,所以@字符仍使用意义)。

同时注意,在需要时你有责任使用 die()。 如果错误处理程序返回了,脚本将会继续执行发生错误的后一行(注意这个,错误处理程序返回后脚本继续执行)。

以下级别的错误不能由用户定义的函数来处理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT(这些级别不能使用自定义函数处理,实际上这些错误根本无法进入到自定义的错误处理程序,这些错误在PHP内核或编译时就被捕获,至于这些错误的处理则是由php.ini文件中的配置决定的,所以当在开发时,最好在php.ini中把display_errors调整为1,error_reporting调整为E_ALL | E_STRICT)。

如果错误发生在脚本执行之前(比如文件上传时),将不会 调用自定义的错误处理程序因为它尚未在那时注册。 ”

从上面的描述来看,我们总结一下:
比较严重的错误,自定义程序无法处理(实际是没有进入这个程序),自定义处理程序只能处理一般错误。一旦使用自定义处理程序来处理错误,那么error_reporting的设置对它是没有作用的(它只处理指定错误处理程序时给定的错误级别)。在开发时,为了能够显示和记录自定义程序无法处理的错误(比如严重错误),应该在php.ini中配置:

1
2
3
display_errors On
error_log /path/to/log/log.txt
error_reporting E_ALL | E_STRICT

注意error_reporting为E_ALL是表示所有错误,但是在PHP5.3中不包含E_STRICT,从PHP5.4开始才包含。display_errors表示从标准错误输出中输出错误,error_log指出记录错误日志的路径。

事实上,我们可以在脚本中改变这些值配置值(而不使用自定义错误处理函数),比如修改error_log,让它把错误记录到我们的指定的日志文件中。比如:http://blog.ifeeline.com/105.html中描述的就是这个情况,但是它只能记录一般错误,对于严重错误,还是根据php.ini配置文件的的设置去处理的。

相对这种记录错误的方法,对应还有一种使用自定义函数的实现方法。这个也是Magento中使用的方法。Magento中有一个叫开发者模式的设置。先记着这个。我们先看看错误处理程序设置的进入点,在index.php文件中有:

1
2
3
error_reporting(E_ALL | E_STRICT);
//接下来有一行注释的代码
#ini_set('display_errors', 1);

首先修改了错误报告的类型,我们知道,如果使用自定义错误处理程序,根本不受它的影响(指error_reporting设置的错误级别)。接下来的代码是设置是否显示错误,这应该是在没有使用自定义错误处理程序时配合使用的,要不然这两句代码大可以清理的了。

我们的应用从App的run方法或init方法开始,run方法调用baseInit,baseInit调用_initEnvironment,_initEnvironment内又调用setErrorHandler(self::DEFAULT_ERROR_HANDLER)方法:

1
2
3
4
5
6
//setErrorHandler(self::DEFAULT_ERROR_HANDLER)  DEFAULT_ERROR_HANDLER->mageCoreErrorHandler
    public function setErrorHandler($handler)
    {
        set_error_handler($handler);
        return $this;
    }

可见,直接使用set_error_handler函数直接设置错误处理程序为mageCoreErrorHandler,这个函数在app/code/core/Mage/Core/functions.php中定义。

1
2
3
4
5
6
7
8
9
function mageCoreErrorHandler($errno, $errstr, $errfile, $errline){
    //...
    $errorMessage .= ": {$errstr}  in {$errfile} on line {$errline}";
    if (Mage::getIsDeveloperMode()) {
        throw new Exception($errorMessage);
    } else {
        Mage::log($errorMessage, Zend_Log::ERR);
    }
}

这里省了一段代码,它罗列的所有错误代码,然后组建一个字符串$errorMessage,然后根据是否是开发模式,如果是就直接抛出异常,否则就把它记录到日志中。如果是记录到日志中,程序继续运行,现在问题是,如果抛出异常,谁来捕获这个异常,如何处理,程序是否继续运行?

这个需要回到App的run方法的包装函数Mage::run()函数中回答这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public static function run($code = '', $type = 'store', $options = array())
 {
     try {
         // .....
         self::$_app->run(array(
             'scope_code' => $code,
             'scope_type' => $type,
             'options'    => $options,
         ));
     } catch (Mage_Core_Model_Session_Exception $e) {
         header('Location: ' . self::getBaseUrl());
         die();
     } catch (Mage_Core_Model_Store_Exception $e) {
         require_once(self::getBaseDir() . DS . 'errors' . DS . '404.php');
         die();
     } catch (Exception $e) {
         if (self::isInstalled() || self::$_isDownloader) {
             self::printException($e);
             exit();
         }
         try {
             self::dispatchEvent('mage_run_exception', array('exception' => $e));
             if (!headers_sent()) {
                 header('Location:' . self::getUrl('install'));
             } else {
                 self::printException($e);
             }
         } catch (Exception $ne) {
             self::printException($ne, $e->getMessage());
         }
     }
 }

很明显,如果自定义错误处理程序抛出异常,就在这里被捕获处理,有些异常是给出链接,有些则是打印输出。这意味,要是打开开发者模式,可以直接查看到错误的输出。

在index.php中有如下代码:

1
2
3
if (isset($_SERVER['MAGE_IS_DEVELOPER_MODE'])) {
    Mage::setIsDeveloperMode(true);
}

两个办法让这个代码生效,把条件去掉,或者在配置中设置MAGE_IS_DEVELOPER_MODE这个变量(一般直接去掉条件快速有实在)。

另外,在自定义的错误处理程序中,如果不是开发模式则不会抛出异常,错误就被记录到日志中,这个路径可以在后台配置:
System->Configuration->Developer->Log Settings
Magento错误日志

在调用Mage::log()函数时记录到System Log File Name,调用Mage::logException时记录到Exceptions Log File Name,实际上logException是log()函数的包装器,只是指定了不同的名字。

到此已经讨论了大部分内容了,我们需要谨记,仅仅依靠Magento中的自定义错误处理程序还是不够的,在开发时务必在PHP中做配置以快速找到错误。而在Magento开启开发者模式则可以直接输出异常信息,另外,可以有效利用Mage:log()来调试程序,它不受配置的影响,可以让它输出到自己期望的地方去。

继续查看在事件触发回调函数调用时的代码:

1
2
3
4
5
6
7
8
9
10
#File: app/code/core/Mage/Core/Model/App.php
protected function _callObserverMethod($object, $method, $observer)
{
    if (method_exists($object, $method)) {
        $object->$method($observer);
    } elseif (Mage::getIsDeveloperMode()) {
        Mage::throwException('Method "'.$method.'" is not defined in "'.get_class($object).'"');
    }
    return $this;
}

当回调函数不存在时,如果在开发模式下,就会抛出异常,这个可以让我们知道哪些回调函数不存在。

Magento中通过使用自定义的错误处理出现,把PHP的错误变成抛出异常。

(责任编辑:最模板)
------分隔线----------------------------
栏目列表
推荐内容