从Guzzle中捕捉exception

我试图从我正在开发的API上运行的一组testing中捕获exception,并使用Guzzle来使用API​​方法。 我已经在try / catch块中包装了testing,但仍然抛出未处理的exception错误。 如他们的文档中所述添加一个事件监听器似乎没有任何作用。 我需要能够检索HTTP代码为500,401,400的响应,实际上不是200的响应,因为如果系统不工作,系统将根据通话结果设置最合适的代码。

当前的代码示例

foreach($tests as $test){ $client = new Client($api_url); $client->getEventDispatcher()->addListener('request.error', function(Event $event) { if ($event['response']->getStatusCode() == 401) { $newResponse = new Response($event['response']->getStatusCode()); $event['response'] = $newResponse; $event->stopPropagation(); } }); try { $client->setDefaultOption('query', $query_string); $request = $client->get($api_version . $test['method'], array(), isset($test['query'])?$test['query']:array()); // Do something with Guzzle. $response = $request->send(); displayTest($request, $response); } catch (Guzzle\Http\Exception\ClientErrorResponseException $e) { $req = $e->getRequest(); $resp =$e->getResponse(); displayTest($req,$resp); } catch (Guzzle\Http\Exception\ServerErrorResponseException $e) { $req = $e->getRequest(); $resp =$e->getResponse(); displayTest($req,$resp); } catch (Guzzle\Http\Exception\BadResponseException $e) { $req = $e->getRequest(); $resp =$e->getResponse(); displayTest($req,$resp); } catch( Exception $e){ echo "AGH!"; } unset($client); $client=null; } 

即使对于抛出的exceptiontypes的具体catch块,我仍然回来

 Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url] 

所有页面上的执行都会停止,就像你期望的那样。 BadResponseException catch的添加允许我正确地捕获404,但这似乎不适用于500或401响应。 任何人都可以build议我哪里错了请。

如果在该try块中抛出exception,那么在最坏的情况下Exception应该捕获任何未被捕获的东西。

考虑到testing的第一部分是抛出exception,并将其包装在try块中。

取决于你的项目,可能需要禁用guzzle的exception。 有时编码规则不允许stream量控制的exception。 你可以像这样禁用Guzzle 3的exception:

 $client = new \Guzzle\Http\Client($httpBase, array( 'request.options' => array( 'exceptions' => false, ) )); 

这不会像超时那样禁用curlexception,但现在您可以轻松获得每个状态码:

 $request = $client->get($uri); $response = $request->send(); $statuscode = $response->getStatusCode(); 

要检查,如果你有一个有效的代码,你可以使用这样的东西:

 if ($statuscode > 300) { // Do some error handling } 

…或更好地处理所有预期的代码:

 if (200 === $statuscode) { // Do something } elseif (304 === $statuscode) { // Nothing to do } elseif (404 === $statuscode) { // Clean up DB or something like this } else { throw new MyException("Invalid response from api..."); } 

For Guzzle 5.3

 $client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] ); 

感谢@mika

对于Guzzle 6

 $client = new \GuzzleHttp\Client(['http_errors' => false]); 

要抓住Guzzle错误,你可以做这样的事情:

 try { $response = $client->get('/not_found.xml')->send(); } catch (Guzzle\Http\Exception\BadResponseException $e) { echo 'Uh oh! ' . $e->getMessage(); } 

…但是,为了能够“login”或“重新发送”您的请求尝试这样的事情:

 // Add custom error handling to any request created by this client $client->getEventDispatcher()->addListener( 'request.error', function(Event $event) { //write log here ... if ($event['response']->getStatusCode() == 401) { // create new token and resend your request... $newRequest = $event['request']->clone(); $newRequest->setHeader('X-Auth-Header', MyApplication::getNewAuthToken()); $newResponse = $newRequest->send(); // Set the response object of the request without firing more events $event['response'] = $newResponse; // You can also change the response and fire the normal chain of // events by calling $event['request']->setResponse($newResponse); // Stop other events from firing when you override 401 responses $event->stopPropagation(); } }); 

…或者如果你想“停止事件传播”,你可以重写事件监听器(比-255更高的优先级),并停止事件传播。

 $client->getEventDispatcher()->addListener('request.error', function(Event $event) { if ($event['response']->getStatusCode() != 200) { // Stop other events from firing when you get stytus-code != 200 $event->stopPropagation(); } }); 

这是一个好主意,以防止像下面这样的错误:

 request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response 

在你的应用程序。

你需要添加一个额外的参数,http_errors => false

 $request = $client->get($url, ['http_errors' => false]); 

老问题,但Guzzle在exception对象内添加了响应。 因此,对GuzzleHttp\Exception\ClientException进行简单的尝试,然后使用getResponse对该exception进行查看,以查看400级别的错误并继续执行。

在我的情况下,我是抛出一个名称空间的文件的Exception ,所以PHP试图赶上My\Namespace\Exception因此不捕捉任何exception。

值得检查是否catch (Exception $e)正在find正确的Exception类。

试试catch (\Exception $e) (用那个\ there),看看它是否有效。

  try { } catch (GuzzleHttp\Subscriber\HttpError $e) { //catches all 4xx and 5xx status codes } 

由于@dado提示我正在捕捉GuzzleHttp\Exception\BadResponseException 。 但有一天,当域名的DNS不可用时,我得到了GuzzleHttp\Exception\ConnectException 。 所以我的build议是 – 赶上GuzzleHttp\Exception\ConnectException也是安全的DNS错误。