【问题标题】:In Laravel/Lumen, why is the catch block not catching my Exception?在 Laravel/Lumen 中,为什么 catch 块没有捕获我的异常?
【发布时间】:2016-02-03 04:46:06
【问题描述】:

在 Laravel/Lumen PHP 框架中捕获异常的最佳方法是什么?这很可能是一个普遍适用于 PHP 的问题。

目前,我有一个 UsersController,它在我的 User 类中调用(在 try 块中)“findByUsernameOrFail”方法。如果找不到用户名,此方法将抛出异常,但 catch 块没有捕获异常!为什么?

class UsersController extends Controller {

    public function show($username)
    {
        try
        {
            $user = \App\User::findByUsernameOrFail($username);

            return $user;
        }
        catch(Exception $e)
        {
            // This doesn't work. This code is never called because Laravel 
            return $this->setStatusCode(404)->respondWithError('Username Not Found!');
        }
    }

此 UsersController 中的“show”方法正在调用 User 模型中名为“findByUsernameOrFail”的方法。如果它通过用户名找到用户,则返回找到的 $user 对象。如果它没有通过用户名找到用户,则会引发异常。然而,由于某种原因,这个异常并没有被捕获,而是 Laravel 正在生成一个通用的错误页面。

这是我的用户模型中的一些代码:

class User extends Illuminate\Database\Eloquent\Model {

    public static function findByUsernameOrFail($username)
    {
        if ( ! is_null($user = static::whereUsername($username)->first()))
        {
            return $user;
        }

        throw new Illuminate\Database\Eloquent\ModelNotFoundException;
    }
}

下面是我尝试运行它时发生的屏幕截图:

为什么我的代码中的“catch”部分从未执行过!?我想要发生的是让我的应用程序优雅地返回一个 HTTP 404 错误,指出找不到用户!根据我对 Try/Catch 和 Exceptions 的了解,我的代码应该可以工作,但显然我遗漏了一些东西。

如何让此代码按照此代码的预期返回 HTTP 404 错误消息?

【问题讨论】:

  • 虽然没有直接关系,但我会使用firstOrFail() 而不是显式抛出异常;把它变成一个单线。 return static::whereUsername($username)->firstOrFail()
  • 有点晚了,但是您是否在UsersController 中导入了顶部带有use Exception; 的异常类?所有异常都应从基 Exception 类扩展,但如果未正确导入,则类型可能与 catch 条件不匹配。

标签: php laravel exception-handling try-catch lumen


【解决方案1】:

我无法用英语解释为什么会这样。我说英语很糟糕。试试把catch(Exception $e)改成catch(ModelNotFoundException $e)

【讨论】:

    【解决方案2】:

    按照建议,您可能需要明确声明您正在侦听的异常。所以正确的方法是

    catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
         // do your stuff.
    } 
    

    但是在 Laravel 中,你可以超越这一点,让它变得非常抽象(就像 Laravel 中的几乎所有东西一样)

    如果您在render 方法中打开app/Exceptions/Handler.php,您可能会监听整个应用程序中抛出的各种异常。

    所以对于你的特殊情况可能如下:

    if ($e instanceof ModelNotFoundException) {
        abort(404);
    }
    

    (不要忘记在顶部导入完整路径)


    正如@Phroggyy 所提到的,您可以利用 Laravel 的 findOrFail() 方法内联您的代码。在幕后,它将完全按照您手动执行的操作 - 尝试查找模型并在未找到时抛出异常。

    【讨论】:

    • 成功了。我必须添加一个 '\' 字符,因此 catch 的最终代码如下所示:catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e).
    • catch (\Exception $e) 在 Laravel 工作,而 catch (Exception $e) 没有。
    • @endo64 是对的,因为一些命名空间原始正常的 php Exception 不知道没有`\`(反斜杠)。
    【解决方案3】:

    使用 捕获(\异常 $e) 代替 捕获(异常 $e)

    【讨论】:

      猜你喜欢
      • 2012-02-24
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-12
      • 2019-04-29
      • 1970-01-01
      • 2021-05-13
      相关资源
      最近更新 更多