我正在使用外部服务(即支付提供商的服务(的API为我的网站实现支付。
假设用户点击"购买",然后我们转到我的控制器,控制器上写着:
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返回一个错误——这意味着它抛出了一个GuzzleException——我该如何处理?
理想情况下,如果出现错误,我希望将其记录下来,并将用户重定向到一个页面,告诉他出了问题。
我尝试过的
我曾尝试在pay((函数中使用try/catch语句并使用
abort(500)
,但这不允许我重定向到我想要的页面。我曾尝试在pay((函数中使用try/catch语句并使用
return redirect('/mypage')
,但这只是向控制器返回一个Redirect对象,然后当它尝试调用result->success
时失败我尝试过使用数字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
捕捉口袋妖怪!
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'));
}
}