编写处理异常的函数


Writing functions that deal with exceptions

基于我已经问过的一个关于异常的问题,我担心当时我可能写错了php函数,或者滥用了异常的使用。我这么说的原因是,如果要使用try/catch块捕获自定义异常,那么下面的函数:

public function get_specific_page($page) {
    if (!is_array( $this->_page )){
        throw new AisisCore_Template_TemplateException( "<div class='error'>Trying to get a property from a non array.</div>" );
    }
    return $this->_page[$page];
}

然后会被称为:

try{
    get_specific_page($page);
}
catch(Exception $e){
    echo $e->getMessage();
}

这种方法的问题是,我有很多这样写的函数,要么检查文件是否存在,要么抛出错误。检查数组中是否设置了值,抛出一个错误,我的问题是处理这些函数调用的文件可能会因try-catch而过载。。。。。

所以我的问题是,我该如何更好地编写这样的函数,这样我就不会在php文件中过度加载try-catch语句,但仍然能够拥有自己的自定义函数。

它是否像在函数内部编写try-catch一样明显?

我问这个问题的原因,如果是因为我习惯于与fameworks合作,以及在我们编写如上所述函数的公司工作的话。我使用过大量这样的函数的代码库,但我没有看到一半使用它们的文件在做一堆尝试捕获。。。

更新:

我查看了zend的来源,以更好地了解异常情况,并发现了以下内容:

public function setMessage($messageString, $messageKey = null)
    {
        if ($messageKey === null) {
            $keys = array_keys($this->_messageTemplates);
            foreach($keys as $key) {
                $this->setMessage($messageString, $key);
            }
            return $this;
        }
        if (!isset($this->_messageTemplates[$messageKey])) {
            require_once 'Zend/Validate/Exception.php';
            throw new Zend_Validate_Exception("No message template exists for key '$messageKey'");
        }
        $this->_messageTemplates[$messageKey] = $messageString;
        return $this;
    }

你可以看到他们是如何在底部附近抛出新的异常消息的,这个函数不是通过执行以下操作来调用的:

try{}catch(){}

然而,当它抛出异常时,"带消息的未捕获异常"

没有问题

在我看来,您的方法总体上是正确的。然而,有几个注意事项:

  1. 您应该避免在异常消息中使用HTML格式。通常,您不知道抛出的异常将如何处理。例如,异常处理程序可以将消息写入日志文件(那时您不需要HTML格式),在一个特殊的错误视图中向用户显示它(在这种情况下,视图本身应该包含HTML格式)或简单地忽略它(无论如何,不需要格式化)
  2. 只捕获您可以处理的异常。如果您知道您的函数抛出了一个AisisCore_Template_TemplateException,那么您应该只捕获该异常,并让所有其他异常冒泡到可以处理它们的异常处理程序中。您可以使用set_exception_handler来定义这样一个异常处理程序,默认情况下它会捕获所有未捕获的异常(Zend Framework中的示例可能就是这种情况)。简单地说:只在您知道如何处理异常的地方捕获异常
  3. 只使用名称所暗示的异常:处理控制流中的(意外)异常。使用异常来控制程序的常规流程是可能的,但通常被认为是糟糕的设计(顺便说一句,代码示例看起来不错)

为了完整起见,使用异常的一些替代方案:

  1. 使用返回代码而不是异常。这是老式的C风格。优点是不需要用try/catch语句包装语句。但是,您必须检查每个过程的返回值,这很容易忘记。另一方面,当使用异常时,可以降低意外错误的风险,因为未捕获的异常在默认情况下会产生致命错误
  2. 使用PHP错误。请参见trigger_error函数。然而,在PHP中几乎不可能捕捉到自定义错误(除了使用仅在全局级别工作的set_error_handler