Laravel HTTP Client

2026-09-14 31

Laravel 项目中,支付、短信、物流、天气和数据同步等功能都可能需要调用第三方 API。Laravel 提供的 HTTP Client 基于 Guzzle 封装,支持请求参数、请求头、超时、状态判断、重试和异常处理,可以减少直接操作底层 HTTP 客户端的代码。

一、发起 GET 请求

Laravel 的 HTTP Client 通过 Http Facade 发起请求:

use Illuminate\Support\Facades\Http;

$response = Http::get('https://api.example.com/users');

可以使用 json() 获取 JSON 响应:

$data = $response->json();

完整示例:

use Illuminate\Support\Facades\Http;

$response = Http::get('https://api.example.com/users');

if ($response->successful()) {
    $users = $response->json();
} else {
    $users = [];
}

successful() 用于判断响应状态码是否为 2xx。

二、传递查询参数

使用 withQueryParameters() 添加 URL 查询参数:

$response = Http::withQueryParameters([
    'page' => 1,
    'limit' => 20,
])->get('https://api.example.com/users');

实际请求地址类似:

https://api.example.com/users?page=1&limit=20

如果项目使用的 Laravel 版本不支持 withQueryParameters(),也可以直接将参数作为 get() 的第二个参数:

$response = Http::get('https://api.example.com/users', [
    'page' => 1,
    'limit' => 20,
]);

三、发送 POST 请求

使用 post() 方法发送 JSON 请求:

use Illuminate\Support\Facades\Http;

$response = Http::post('https://api.example.com/orders', [
    'user_id' => 1001,
    'amount' => 19900,
]);

Laravel 会将数组作为 JSON 请求体发送。也可以使用 asForm() 发送表单格式数据:

$response = Http::asForm()->post('https://api.example.com/login', [
    'username' => 'demo',
    'password' => 'example-password',
]);

密码等敏感信息不应直接写入代码,应从环境变量或安全配置中读取。

四、设置请求头

通过 withHeaders() 设置请求头:

$response = Http::withHeaders([
    'Accept' => 'application/json',
    'X-Client-Version' => '1.0.0',
])->get('https://api.example.com/profile');

调用需要 Bearer Token 的接口时,可以使用:

$response = Http::withToken($token)
    ->acceptJson()
    ->get('https://api.example.com/profile');

$token 应来自安全配置或数据库中的有效凭证,不能提交到公开代码仓库。

五、设置超时时间

第三方接口响应过慢时,可能拖延当前请求。可以设置连接超时和整体请求超时:

$response = Http::connectTimeout(3)
    ->timeout(10)
    ->get('https://api.example.com/status');

其中:

  • connectTimeout(3):连接服务器最多等待 3 秒。
  • timeout(10):整个请求最多等待 10 秒。

实际时间应结合业务场景设置。支付、订单和数据同步等接口需要根据服务商要求设计超时策略。

六、判断请求结果

Laravel HTTP Client 提供多种状态判断方法:

if ($response->successful()) {
    // 2xx
}

if ($response->failed()) {
    // 4xx 或 5xx
}

if ($response->clientError()) {
    // 4xx
}

if ($response->serverError()) {
    // 5xx
}

也可以直接判断状态码:

if ($response->status() === 200) {
    $data = $response->json();
}

如果只接受成功响应,可以使用 throw()

$response = Http::get('https://api.example.com/users')
    ->throw();

$data = $response->json();

当接口返回 4xx 或 5xx 时,throw() 会抛出异常。业务代码可以通过 try...catch 进行处理:

use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Http;

try {
    $response = Http::timeout(10)
        ->get('https://api.example.com/users')
        ->throw();

    $data = $response->json();
} catch (RequestException $exception) {
    report($exception);

    $data = [];
}

七、处理请求失败和重试

网络抖动、服务临时过载或网关错误可能导致请求失败。可以使用 retry() 自动重试:

$response = Http::retry(3, 200)
    ->timeout(10)
    ->get('https://api.example.com/status');

这表示最多尝试 3 次,每次重试间隔 200 毫秒。

如果希望只对特定异常进行重试,可以传入闭包:

$response = Http::retry(3, 200, function (
    \Exception $exception,
    $request
) {
    return $exception instanceof \Illuminate\Http\Client\ConnectionException;
})->get('https://api.example.com/status');

对于支付、订单创建等可能产生业务副作用的请求,不能简单重复发送。重试前应确认接口是否支持幂等键,否则可能造成重复订单或重复扣款。

八、封装第三方 API 服务

当多个控制器都需要调用同一个接口时,可以将请求逻辑放到服务类中。

创建文件:

app/Services/WeatherService.php

写入:

<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class WeatherService
{
    public function getCityWeather(string $city): array
    {
        $response = Http::acceptJson()
            ->connectTimeout(3)
            ->timeout(10)
            ->retry(2, 200)
            ->get(config('services.weather.url'), [
                'city' => $city,
            ])
            ->throw();

        return $response->json();
    }
}

config/services.php 中配置地址:

'weather' => [
    'url' => env('WEATHER_API_URL'),
],

.env 中设置:

WEATHER_API_URL=https://api.example.com/weather

控制器中调用:

use App\Services\WeatherService;

class WeatherController
{
    public function show(
        WeatherService $weatherService,
        string $city
    ) {
        return response()->json(
            $weatherService->getCityWeather($city)
        );
    }
}

将地址放入配置文件后,可以根据开发、测试和生产环境使用不同的接口地址。

九、测试 HTTP 请求

Laravel 支持使用 Http::fake() 模拟外部接口:

use Illuminate\Support\Facades\Http;

Http::fake([
    'api.example.com/*' => Http::response([
        'status' => 'ok',
    ], 200),
]);

然后执行业务代码:

$response = Http::get('https://api.example.com/status');

$this->assertTrue($response->successful());

还可以验证请求是否发送了正确参数:

Http::assertSent(function ($request) {
    return $request->url() === 'https://api.example.com/status'
        && $request->header('Accept')[0] === 'application/json';
});

测试时使用模拟响应,可以避免频繁调用真实第三方接口。

十、常见问题

HTTP Client 请求失败会自动重试吗?

不会。只有调用 retry() 后,Laravel 才会按照指定次数和间隔进行重试。

timeout()connectTimeout() 有什么区别?

connectTimeout() 控制建立连接的等待时间,timeout() 控制整个请求的最大执行时间。实际接口调用通常建议同时设置。

所有接口都适合自动重试吗?

不适合。查询类请求通常更容易重试,创建订单、支付和扣库存等操作需要先确认接口幂等机制。

  • 广告合作

  • QQ群号:4114653

温馨提示:
1、本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com(#改为@)。 2、本站原创内容未经允许不得转裁,转载请注明出处“站长百科”和原文地址。
Laravel
上一篇: Laravel多语言开发
Laravel
下一篇: Laravel通知系统