最佳实践:在php-doc中使用@throws,以及如何处理它

2022-08-30 11:55:05

假设我有一个类,其方法如下:

/*
 *
 * 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原因抛出/ / 。我该怎么办?什么不是?someFunctionInvalidArgumentExceptionRuntimeExceptionPDOException

第 1 步

添加所有可能在 php 文档中引发的异常。someFunction

/*
 *
 * 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 步

不要做任何事情。


答案 1

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

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

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

当方法具有批注时,必须添加代码来处理其异常。@throws

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


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


答案 2

关于文档,如果函数显式引发异常,则应将其包含在函数的文档中。因此,对于每个语句,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
}

推荐