在以下身份验证类示例中抛出异常时,建议针对要处理的每种情况抛出不同的异常,例如:
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;
}
我问是因为我是例外的新手,两种解决方案似乎同样可行。也许完全有其他解决方案?
有趣的旁注:直到收到一些答案后,我才意识到我在问一个"你的偏好是什么"的问题。我期待一种推荐的方法。
我不会说一种方式是对的,一种方式是错误的——如果这个问题击中了一大群人的正确神经,问"这是推荐的还是这种方式的"很容易激起一大锅。
特别是关于您的问题,两者都是引发不同类型异常的有效且可接受的方法 - 我经常看到这两种异常。
然而,在几乎所有语言的大规模应用程序中,我经常看到底部方法 - 这也是我自己的个人风格/偏好。我认为抛出单个"类型"的异常,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
是最简单的方法(不使用第 3 方类/插件。
一般来说,我认为最佳实践是例外应包含单个例外条件。 以声压级例外为例。 你会扔InvalidUserArgumentException
和InvalidEmailArgumentException
吗? 不。 您将抛出 SPL InvalidArgumentException
,然后根据详细信息更改异常消息(例如"无效用户"或"无效电子邮件")。 也就是说,恕我直言,您应该使用单个AuthException
并改变消息(就像您在第二个示例中所做的那样),只是不使用代码和开关,只需直接输出异常消息:
try {
$auth->adduser(...);
} catch (AuthException $e) {
$output = $e->getMessage();
}
echo $output;
我更喜欢顶级方式,即对可能发生的每个异常都有一个单独的 catch 语句,但这取决于。.如果你发现自己有很长的异常类名,很难理解它们的含义,那么我会把它们分组一下。