You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

构建The Movie Database API类封装时Guzzle 7未抛出异常的问题

看起来你遇到的问题是Guzzle没有在使用错误API密钥时抛出异常,我来帮你分析可能的原因和解决办法:

可能的原因分析

1. TMDB API的错误响应可能不触发HTTP状态码异常

很多API(包括TMDB)在某些错误场景下,可能返回200状态码但在响应体中包含错误信息,比如无效API密钥时,返回的JSON结构大概是这样:

{
  "success": false,
  "status_code": 7,
  "status_message": "Invalid API key: You must be granted a valid key."
}

这种情况下,Guzzle的http_errors=true不会抛出异常——因为HTTP状态码是200(属于正常范围),只有当状态码≥400时,Guzzle才会触发HTTP异常。

2. 请求参数的构造可能存在问题

你用Middleware::mapRequest来添加api_key和language到Uri的查询参数,但同时在get请求里又传了['query' => compact('query')]选项。虽然Guzzle会合并这两部分查询参数,但你可以先确认最终的请求Uri是否正确携带了错误的API密钥——如果参数没正确传递,TMDB可能不会返回错误。

3. 异常捕获的逻辑覆盖不全

虽然你捕获了GuzzleException(所有Guzzle异常的基类),但如果请求没有触发HTTP错误(比如返回200带错误内容),自然不会进入catch块。

解决方案

步骤1:主动检查响应体中的TMDB错误信息

不管HTTP状态码如何,都要解析响应体,手动检查TMDB返回的错误标识:

public function search($screenplayType, $query): ?array {
    try {
        $response = $this->client->get('search/' . $screenplayType, [
            'query' => compact('query')
        ]);
        $body = json_decode($response->getBody(), true);
        
        // 检查TMDB返回的错误字段
        if (isset($body['success']) && !$body['success']) {
            throw new \Exception($body['status_message'] ?? 'Unknown TMDB error');
        }
        
        return $this->toModel((object)$body, $screenplayType);
    } catch (GuzzleException $e) {
        echo 'HTTP Error: ' . $e->getMessage();
        return null;
    } catch (\Exception $e) {
        echo 'TMDB Error: ' . $e->getMessage();
        return null;
    }
}

步骤2:确认请求参数是否正确传递

可以在middleware里临时添加日志,打印最终的请求Uri,确认api_key是否被正确携带:

$handlerStack->unshift(Middleware::mapRequest(function (RequestInterface $request) {
    $uri = Uri::withQueryValues($request->getUri(), [
        'api_key' => $this->apiKey,
        'language' => $this->language
    ]);
    // 临时打印Uri到错误日志,方便排查
    error_log('Final Request Uri: ' . (string)$uri);
    return $request->withUri($uri);
}));

步骤3:显式配置Guzzle的http_errors参数

虽然默认值是true,但可以在Client构造中显式指定,避免被其他配置意外覆盖:

$this->client = new Client([
    'base_uri' => self::API_URL,
    'handler' => $handlerStack,
    'http_errors' => true // 显式开启HTTP错误异常
]);

步骤4:捕获更具体的异常(可选)

如果你想区分不同类型的Guzzle异常,可以捕获更具体的子类:

use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;

// ...

catch (ClientException $e) {
    // 处理4xx客户端错误(比如401、404)
    echo 'Client Error: ' . $e->getMessage();
} catch (ServerException $e) {
    // 处理5xx服务器错误
    echo 'Server Error: ' . $e->getMessage();
} catch (GuzzleException $e) {
    // 处理其他Guzzle异常
    echo 'Guzzle Error: ' . $e->getMessage();
}

内容的提问来源于stack exchange,提问作者Michael Cozzolino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:07:35