从方法内部处理异常

Handle Exception From Within Method

我正在使用外部服务(即支付提供商的服务)的 API 为我的网站实施支付。

假设用户点击 'BUY',然后我们转到我的控制器,它说的是:

public function buyFunction() {

    $result = $this->ExternalService->pay();

    if ($result->success == true) {
        return 'We are happy';
    }
}

我还创建了前面提到的 externalService,它具有 pay() 方法:

class ExternalService {

    public function pay() {
        response = //Do stuff with Guzzle to call the API to make the payment

        return response;
    }
}

现在,有时候事情会出错。 假设 API returns 一个错误 - 这意味着它抛出 GuzzleException - 我该如何处理?

理想情况下,如果有错误,我想记录它并将用户重定向到一个页面并告诉他出了点问题。

我试过的

  1. 我尝试在 pay() 函数中使用 try/catch 语句并使用 abort(500) 但这不允许我重定向到我想要的页面。

  2. 我试过在 pay() 函数中使用 try/catch 语句并使用 return redirect('/mypage') 但这只是 returns 到控制器的重定向对象,它然后在尝试调用 result->success

    时失败
  3. 我试过使用数字 2,但也在控制器方法中添加了一个 try/catch 块,但没有任何改变。

最后,我找到了两个解决方案。在两者中,我都在 pay() 方法中使用了 try/catch 块。然后我 return 0; 并检查控制器 if (result == 0) 或者我在 pay() 方法的 try/catch 块内使用 abort( redirect('/mypage') );

处理这个问题的正确方法是什么? 如何使用try/catch块?

根据我的经验,避免处理异常让它们通过并使用 try catch 相应地处理它们。这是最实用的方法。或者,您最终会在奇怪的地方检查结果是否正确,例如。 if ($result) {...}。假设一切顺利,除非抛出异常。额外奖励:除非你特别需要,否则永远不要用 Exception $e 捕捉 Pokemon!

class ExternalService {

    public function pay() {
        try {
            response = $client->get(...);
        } catch (BadResponseException $exception) {
            Log::warning('This should not happen check payment api: ' . $exception->getMessage());
            
            throw new PaymentException('Payment did not go through');
        } 

        return response;
    }
}

假设您有自己的异常。

class PaymentException extends HttpException
{
    public function __construct(?\Exception $previous = null)
    {
        parent::__construct(Response::HTTP_BAD_REQUEST, 'Unexpected error processing the payment', $previous);
    }
}

这使您能够在控制器中处理流,在控制器中处理重定向是有意义的。有时,如果异常对于 Web 应用来说是不可或缺的或常见的,它也可以由异常处理程序来处理。

class PaymentController {
    public function pay(PaymentService $service) {
        try {
            $payment = $service->buyFunction();
        } catch (PaymentException $exception) {
            return redirect()->route('app.payment.error');
        } 
        
        return view('app.payment.success', compact('payment'));
    }
}