Laravel 5.5自定义异常处理器调用报错问题求助
我在Laravel 5.5里想重构异常处理逻辑,把原本在默认app\Exceptions\Handler.php里处理422状态码的ClientException逻辑,移到自定义异常类里。原本的默认处理器逻辑是正常的,但重构后出现了这个错误:
Type error: Argument 2 passed to App\Exceptions\HttpExceptions\UnprocessableEntityException::render() must be an instance of GuzzleHttp\Exception\ClientException, none given, called in ... \vendor\laravel\framework\src\Illuminate\Foundation\Exceptions\Handler.php on line 169
错误原因分析
咱们先搞清楚问题出在哪:
- Laravel框架调用异常的
render方法时,只会传两个参数:第一个是$request,第二个是当前抛出的那个异常实例(也就是你自己定义的UnprocessableEntityException),而不是原来的Guzzle ClientException。 - 你现在的自定义异常
render方法要求第二个参数是ClientException,这和Laravel传递的参数类型不匹配,自然就报类型错误了。 - 另外,你抛出自定义异常的时候,也没把原始的ClientException传递进去,就算类型匹配了,也拿不到错误信息。
解决方案
咱们一步步来修正:
1. 修改自定义异常类,存储原始ClientException
更新app\Exceptions\HttpExceptions\UnprocessableEntityException.php,让它接收并保存原始的ClientException实例,同时调整render方法的参数:
<?php namespace App\Exceptions\HttpExceptions; use GuzzleHttp\Exception\ClientException; use Illuminate\Http\Request; class UnprocessableEntityException extends \Exception { // 存储原始的ClientException protected $originalException; // 构造方法接收原始异常 public function __construct(ClientException $exception) { $this->originalException = $exception; parent::__construct($exception->getMessage(), $exception->getCode(), $exception); } // render方法只接收$request参数,使用存储的原始异常处理 public function render(Request $request) { $errors = json_decode((string) $this->originalException->getResponse()->getBody(), true)["errors"]; return back()->withErrors($errors); } }
2. 调整控制器中抛出异常的代码
在ProfileController.php里,抛出自定义异常时把原始的ClientException传进去:
public function update(Request $request, $id){ try { $this->guzzleService->put( $request, ApiEndPoints::UPDATE_PROFILE . $id, true ); return back()->with('SavedCorrectly', 'Cambios guardados correctamente'); } catch(ClientException $exception) { if ($exception->getCode() == 500) throw new InternalServerErrorException($exception); // 同样要传原始异常 if ($exception->getCode() == 422) throw new UnprocessableEntityException($exception); } }
3. (可选)确保默认Handler能识别自定义异常
如果你的默认Handler.php没有自动处理自定义异常的话,其实Laravel会自动调用异常自身的render方法,不过可以确认一下render方法里有没有覆盖逻辑,保持默认的parent::render调用即可:
public function render($request, Exception $exception) { // 其他自定义逻辑... return parent::render($request, $exception); }
这样修改后,自定义异常就能正确拿到原始的ClientException信息,也符合Laravel的异常处理机制,不会再报类型错误了。
内容的提问来源于stack exchange,提问作者Sergio

