什么是异常处理的正确方法?


20

在Joomla核心中,我仍然发现许多这样的调用:

    // Check for errors.
    if (count($errors = $this->get('Errors')))
    {
        JError::raiseError(500, implode("\n", $errors));
        return false;
    }

但是从平台版本12.1开始不推荐使用JError。那么我应该如何使用标准的PHP异常。


1
不幸的是,从JError到PHP的区别是Errors不仅仅是单击过程。因此,如果您确定将要获得异常,请执行try / catch语句,如下面的答案所示。如果您确定要获取JError,则需要执行与上述类似的代码:)
George Wilson

Answers:


17

正如@DmitryRekun所说的,这里是一个很好的讨论。所有这一切中要考虑的关键是您有哪种类型的错误?

错误有两种:

  1. 可恢复的
  2. 无法恢复。

我倾向于总结出如下差异:

Can I still show the page that was requested, even though this error occurred?
  • 是?-可恢复
  • 没有?-无法恢复

现在我们知道了要处理的内容。你该怎么办?

如果错误无法恢复,您想将它们重定向到错误页面,而不是继续到请求的页面。这很简单,如下所示:

throw new Exception(JText::_('COM_MYCOMP_ERROR_MESSAGE_NOT_FOUND'), 404);

Exception是一个带有两个参数(消息和代码)的类。如果适合您的情况,建议尝试使用HTTP响应代码

如果错误是可恢复的,则您可能只想向最终用户显示一条消息,同时仍向他们显示他们请求的页面。这通常意味着您应该为应用程序“排队”消息:

JFactory::getApplication()->enqueueMessage($error, 'error');

enqueueMessage具有两个参数,错误消息和消息类型。更多信息在这里(底部)。


至少对我而言,还有第三种情况经常发生。Joomla将针对不同的错误(例如数据库查询错误)抛出异常。这意味着Joomla认为此错误是无法恢复的。但是,您可能仍要继续。(例如,如果要在扩展名更新时更改表,则可以运行ALTER查询,如果该表先前已更改,则将引发异常。)

在这种情况下,您想将可能引发异常的代码包装在try ... catch部分中:

try {
    // exception generating code
    throw new Exception('Normally you would have other code that calls a class that throws the exception', 500);
} catch (Exception $e) {
    $msg = $e->getMessage(); // Returns "Normally you would have other code...
    $code = $e->getCode(); // Returns '500';
    JFactory::getApplication()->enqueueMessage($msg, 'error'); // commonly to still display that error
}

请注意,您正在执行的操作是“捕获”不可恢复的错误,并迫使系统恢复并继续显示请求的页面。


将所有这些加起来,您的案例应该是不可恢复的错误。(我知道这一点是因为之后您会返回“ false”,因此您可能不打算继续并放弃该功能。)

因此,我将其重写如下:

// Check for errors.
if (count($errors = $this->get('Errors')))
{
    throw new Exception(implode("\n", $errors), 500);
    return false; // you can remove this too, technically since the exception will take you out of this function.
}

好答案!但我不会依靠,$this->get('Errors')因为它也已弃用。
德米特里·雷昆2014年

对失败的断言(即内部错误)有何评论?我希望程序在失败的断言后立即终止-是否有Joomla特定的方法来执行此操作?目前,我注册了一个断言处理器(如果JDEBUG是)true
OlleHärstedt

12

这是我处理错误的方法。

视图或控制器

try
{
    $this->item = $this->get('Item');
}
catch (Exception $e)
{
    if ($e->getCode() == 404)
    {
        // Not found
        throw new Exception($e->getMessage(), 404);
    }

    // Generic errors
    JFactory::getApplication()->enqueueMessage(JText::_('COM_MYCOMP_ERROR_OCCURRED'), 'error');
}

因此,如果我从模型中获得404代码(例如):

if (empty($data))
{
    throw new Exception(JText::_('COM_MYCOMP_ERROR_MESSAGE_NOT_FOUND'), 404);
}

然后,我将其捕获到视图或控制器中,并抛出另一个Joomla将处理并显示404页面的异常。对于其他任何内容,我只向用户显示一些常规错误消息。

还请阅读有关错误处理的有趣讨论。


4

像这样的大多数代码块都可以简单地替换为enqueueMessage它们,因为它们实际上并没有对错误起作用,而只是JError用来将它们打印出来。

// Check for errors.
if (count($errors = $this->get('Errors'))) {
    foreach($errors as $error) {
        JFactory::getApplication()->enqueueMessage($error, 'error');
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.