1

在以下 auth 类示例中抛出异常时,建议针对要处理的每种情况抛出不同的异常,例如:

addUser(...) {

    // normal database code here...

    switch(TRUE) {
        case ($username_exists):
            throw new UserExists('Cannot create new account. Account username ' . $un . ' already exists.');
        case ($email_exists):
            throw new EmailExists('Cannot create new account. Account email ' . $email . ' already exists.');
    }
}

   //to be called externally by...

try {
    $auth->adduser(...);
} catch (UserExists) {
    $output = 'That username is already taken.';
} catch (EmailExists) {
    $output = 'That email is already being used.';
} catch (AuthException $e) {
    $output = $e->getMessage();
}

echo $output;
}

还是建议使用唯一的异常代码抛出一般“类型”的异常?例如...

addUser(...) {

    // normal database code here...

    switch(TRUE) {
        case ($username_exists):
            throw new AuthException('Cannot create new account. Account username ' . $un . ' already exists.', 10);
        case ($email_exists):
            throw new AuthException('Cannot create new account. Account email ' . $email . ' already exists.', 20);
    }
}

   //to be called externally by...

try {
    $auth->adduser(...);
} catch (AuthException $e) {
    switch($e->getCode()) {
        case 10:
            $output = 'That username is already taken.';
            break;
        case 20:
            $output = 'That email is already being used.';
            break;
        default:
            $output = $e->getMessage();
    }
echo $output;
}

我问是因为我对例外不熟悉,而且两种解决方案似乎都同样可行。也许完全有其他解决方案?

有趣的旁注:直到收到一些答案后,我才意识到我在问“你的偏好是什么”的问题。我期待一个单一的推荐方法。

4

3 回答 3

1

一般来说,我认为最好的做法是异常应该包含一个异常条件。以 SPL 异常为例。你会抛出InvalidUserArgumentExceptionandInvalidEmailArgumentException吗?没有。您将抛出 SPLInvalidArgumentException并根据详细信息(例如“无效用户”或“无效电子邮件”)更改异常消息。也就是说,恕我直言,您应该使用一个AuthException并且只是改变消息(就像您在第二个示例中所做的那样),而不是使用代码和开关,直接输出异常消息:

try {
    $auth->adduser(...);
} catch (AuthException $e) {
    $output = $e->getMessage();
}

echo $output;
于 2012-08-17T19:06:05.857 回答
1

我不会说一种方式是对的,一种方式是错误的——如果这个问题在一大群人中触及正确的神经,那么问一个“推荐这种方式还是这种方式”很容易激起一个大锅。

具体来说,关于您的问题,两者都是引发不同类型异常的有效且可接受的方法 - 我经常看到这两种方法。

然而,在几乎所有语言的大规模应用程序中,我经常看到底部方法 - 这也是我自己的个人风格/偏好。我认为抛出一个单一的“类型”异常AuthException,并指定一个异常代码是非常清晰和简洁的。

如果您希望它更具描述性(从编程的角度来看),您可以enum对代码使用伪 * 设置以提供用户友好的描述:

class AuthExceptionCode {
    const USER_EXISTS = 0;
    const EMAIL_EXISTS= 1;
    // ....
}

用代码抛出异常:

throw new AuthException('error message', AuthExceptionCode::USER_EXISTS);

如果您有一个实际的自定义Exception类,即您extend Exception,您可以将代码方向放在类本身中:

class AuthException extends Exception {
    const MISC = -1;
    const USER_EXISTS = 0;
    const EMAIL_EXISTS= 1;

    public function __construct($message, $code = self::MISC) {
        switch ($code) {
            case self::USER_EXISTS:
                // example on how to access the codes from within the class
                // ...


*Enumerations不是 PHP 原生的,所以使用const是最简单的方法(不使用 3rd-party 类/插件。

于 2012-08-17T19:18:11.157 回答
0

我更喜欢对可能发生的每个异常都有一个单独的 catch 语句的最佳方式,但这取决于.. 如果你发现自己有很长的异常类名称,很难理解它们的含义,那么我会将它们分组一点.

于 2012-08-17T18:54:23.250 回答