40

假设我有一个具有如下方法的类:

/*
 *
 * Loads the user from username.
 *
 * @param string $username The username
 *
 * @return UserInterface
 *
 * @throws userNotFoundException if the user is not found
 */
public function getUser($username)
{
    // someFunction return an UserInterface class if found, or null if not.
    $user = someFunction('SELECT ....', $username);
    if ($user === null) {
        throw new userNotFoundException();
    }

    return $user
}

现在假设由于 XYZ 原因someFunction可能会抛出一个InvalidArgumentException// RuntimeExceptionPDOException我该怎么办?什么不是?

1号

添加所有可能someFunction在 php-docs 中抛出的异常。

/*
 *
 * Loads the user from username.
 *
 * @param string $username The username
 *
 * @return UserInterface
 *
 * @throws userNotFoundException if the user is not found
 * @throws InvalidArgumentException
 * @throws ...
 */

2号

添加一个 try-catch 块以确保该方法应该抛出异常,仅记录在案

/*
 *
 * Loads the user from username.
 *
 * @param string $username The username
 *
 * @return UserInterface
 *
 * @throws userNotFoundException if the user is not found
 * @throws RuntimeException 
 */
public function getUser($username)
{
    try {
        $user = someFunction('SELECT ....', $username);
    } catch (Exception $e) {
        throw new RuntimeException();
    }

    if ($user === null) {
        throw new userNotFoundException();
    }

    return $user
}

3 号

不要做任何事。

4

4 回答 4

24

就我个人而言,我会考虑处理@throws类似于 Java 的已检查异常

这在 Java 中的工作方式是基本上可以抛出从 RuntimeException 继承的异常,而不必处理。任何其他类型的异常都必须有一个 try-catch 块来处理它们。此处理代码必须在调用者中。

基本上在 PHP 中有点像这样:

当一个方法有@throws注解时,你必须添加代码来处理它的异常。

任何未提及的异常对于调用代码中的处理都是可选的。


现在,我自己并没有 100% 遵循这个原则。整个处理异常的事情有点取决于程序员的偏好,但这只是我认为如何以合理的方式处理它的一些想法。

于 2013-03-23T13:55:55.707 回答
12

关于文档,如果一个函数显式抛出异常,那么它应该包含在函数的文档中。因此,对于每条语句,在 PHP 文档中throw都应该有对应的。@throws

关于处理,如果抛出异常时应该执行一些操作,则捕获它。否则,让它冒泡——前提是catch稍后有一个声明来处理它。

更新:

几年后,我改变了这样一种观点,即只有当异常仍然与模块的抽象级别相关时,才应该让异常“冒泡”而不加修改。应采用捕获和重新抛出策略以使异常更有意义。它还应该通过避免不必要地泄露有关抽象底层模块的信息来使错误处理更加安全。

/**
 * @throws UserNotFoundException
 */
public function getUser($username)
{
    try {
        $user = someFunction('SELECT ....', $username);
    } catch (DatabaseException $dbe) {

        /* Re-throw since a database exception may no longer be
         * meaningful to the caller.
         */
        throw new UserNotFoundException();
    }

    return $user
}
于 2013-03-23T14:58:50.797 回答
8

从文档维护的角度来看,我只会为特别抛出的异常添加@throw 行,否则您将很快使您的文档过时。

于 2013-03-23T13:56:04.587 回答
0

第二,但可能在返回之前抛出,因为抛出动作将在返回之前发生......

于 2018-11-27T10:28:26.653 回答