如何处理 Laravel 5.4 中的异常?

How do I deal with Exceptions in Laravel 5.4?

我正在使用 Laravel 5.4 并且我正在使用 Stripe 作为支付处理器。

Stripe 方面似乎在工作,但我正在努力处理例外情况。下面的代码以前似乎可以正常工作,但也许它使用的是缓存中已被清除的文件:

namespace App\Http\Controllers;

// Do I need to use anything at the top??
// use Exception; 

class ItemController extends Controller
{
    public function postCheckout(Request $request, Exception $e)
    {
        if ($e instanceof \Illuminate\Session\TokenMismatchException) {
            return redirect()->back()->withInput()->with(
                'token', csrf_token()
            );
        }

        try {
            // ...
        } catch (\Exception $e) {
            return redirect()->route('checkout')->with(
                'error', $e->getMessage()
            );
        }
    }
}

给出错误:

(1/1) ReflectionException
Class App\Http\Controllers\Exception does not exist
in RouteSignatureParameters.php (line 25)

如果我从方法中删除 Exception $e 参数,并注释掉 iftry 语句,则成功付款将按预期处理。

我做错了什么?

编辑

如果我说 \Exception $e 我得到:

(1/1) BindingResolutionException
Unresolvable dependency resolving [Parameter #0 [ <optional> $message ]] in class Exception
in Container.php (line 910)

让我们在 PHP 中了解命名空间和 type-hinting。如果你这样编码:

namespace App\Http\Controllers;

class ItemController extends Controller
{
    public function postCheckout(Request $request, Exception $e)
    {
        ...
    }
}

这意味着您的 postCheckout 方法期望第二个参数是 class App\Http\Controllers\Exception 的实例。这就是为什么如果这个异常 class 不存在,你会得到这样的错误:

Class App\Http\Controllers\Exception does not exist

我不确定你的情况,因为我不知道如何从你的代码的另一部分调用这个 postCheckout 方法。但是,如果您希望第二个参数是 built-in PHP Exception class,您可以使用 full-path 命名空间,如下所示:

namespace App\Http\Controllers;

class ItemController extends Controller
{
    public function postCheckout(Request $request, \Exception $e)
    {
        ...
    }
}

或者您也可以导入上面预期的 class 命名空间:

use Exception;
namespace App\Http\Controllers;

class ItemController extends Controller
{
    public function postCheckout(Request $request, Exception $e)
    {
        ...
    }
}

而第二个错误的发生是因为Laravel的容器无法解析postCheckout方法所需的依赖关系。

(1/1) BindingResolutionException
Unresolvable dependency resolving...

根据这个错误和你的 class 的名称,我假设你使用这个 postCheckout 方法作为路由处理程序?

Route::post('/foo', 'ItemController@postCheckout');

如果是这种情况,那么这不是您使用 Laravel 捕获异常的方式。要处理 Laravel 中的异常,您可以在 app/Exceptions/Handler.php 文件中进行。那里有两种方法:

  1. report: 如果你想用自定义格式记录异常。
  2. render:如果您想 return 自定义 HTTP 响应到该异常。

对于您的情况,您需要自定义响应:

public function render($request, Exception $exception)
{
    if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
        // Perform the exception handler here
    }

    return parent::render($request, $exception);
}

同样的事情也适用于您的 Stripe 相关异常,您可以在此 Handler class 中处理它。阅读更多关于 The render Method.

希望这能给你一些想法。