HTTP请求类库封装分享,因为最近项目涉及到异步的请求 我加上了

封装优点:

1.简单的可以发送各种请求
2.可以发送异步的各种请求
3.请求的时候 创建 实例的时候 都可以修改 各项参数
4.提供单例模式,可以在某个方法内如果多次请求的话,可以共享cookies等信息

<?php

namespace App\Services;

use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\ResponseInterface;

/**
 * HttpClient类 - HTTP请求客户端工具
 *
 * 基于GuzzleHttp封装的HTTP客户端,支持同步和异步请求,
 * 提供单例模式和链式调用,简化HTTP请求操作
 */
class HttpClient
{
    /**
     * @var HttpClient|null $instance 单例模式的静态实例
     */
    private static $instance = null;

    /**
     * @var Client $client Guzzle HTTP客户端实例
     */
    private $client;

    /**
     * @var array $headers 全局请求头设置
     */
    private $headers = [];

    /**
     * @var array|null $proxy HTTP代理设置
     */
    private $proxy = null;

    /**
     * HttpClient构造函数
     *
     * 初始化Guzzle HTTP客户端,设置默认配置
     *
     * @param array $config 自定义配置项,将覆盖默认配置
     */
    public function __construct($config = [])
    {
        // 默认配置参数
        $default_config = [
            'connect_timeout' => 10 * 60,   // 连接超时时间,10分钟
            'timeout'         => 10 * 60,   // 请求超时时间,10分钟
            'read_timeout'    => 10 * 60,   // 读取超时时间,10分钟
            'verify'          => false,     // 不验证SSL证书
            'http_errors'     => false,     // 不抛出HTTP错误异常
            'allow_redirects' => false,     // 默认不跟随重定向
        ];

        // 初始化Guzzle客户端,合并默认配置和用户配置
        $this->client = new Client(array_merge($default_config, $config));
    }

    /**
     * 获取HttpClient的单例实例
     *
     * 如果实例不存在则创建新实例,否则返回已有实例
     *
     * @param array $config 配置项参数
     * @return HttpClient 返回HttpClient实例
     */
    public static function getInstance($config = [])
    {
        if (self::$instance === null) {
            self::$instance = new self($config);
        }
        return self::$instance;
    }

    /**
     * 设置全局HTTP请求头
     *
     * @param array $headers 请求头数组,格式为['Header-Name' => 'value']
     * @return $this 返回当前实例,支持链式调用
     */
    public function setHeaders($headers)
    {
        $this->headers = array_merge($this->headers, $headers);
        return $this;
    }

    /**
     * 设置请求的cookies
     *
     * 将cookies数组转换为cookie字符串并设置到请求头中
     *
     * @param array $cookies cookie数组,格式为['name' => 'value']
     * @return $this 返回当前实例,支持链式调用
     */
    public function setCookies(array $cookies)
    {
        // 构造cookie字符串,格式为"name1=value1; name2=value2"
        $cookie_str = '';
        foreach ($cookies as $key => $value) {
            $cookie_str .= "{$key}={$value}; ";
        }
        $cookie_str = rtrim($cookie_str, '; ');

        // 设置Cookie请求头
        $this->headers['Cookie'] = $cookie_str;
        return $this;
    }

    /**
     * 设置HTTP代理
     *
     * 为HTTP和HTTPS请求设置代理服务器
     *
     * @param string $proxy 代理服务器地址,例如"http://127.0.0.1:8080"
     * @return $this 返回当前实例,支持链式调用
     */
    public function setProxy($proxy)
    {
        $this->proxy = [
            'http'  => $proxy,
            'https' => $proxy,
        ];
        return $this;
    }

    /**
     * 发送GET请求
     *
     * @param string $url 请求URL
     * @param array $data 查询参数数组
     * @param array $options 额外的请求选项
     * @return ResponseInterface 返回响应对象
     */
    public function get($url, $data = [], $options = [])
    {
        $options['query'] = $data;
        return $this->request('GET', $url, $options);
    }

    /**
     * 发送POST表单请求
     *
     * @param string $url 请求URL
     * @param array $data POST表单数据
     * @param array $options 额外的请求选项
     * @return ResponseInterface 返回响应对象
     */
    public function post($url, $data = [], $options = [])
    {
        $options['form_params'] = $data;
        return $this->request('POST', $url, $options);
    }

    /**
     * 发送JSON格式的POST请求
     *
     * @param string $url 请求URL
     * @param array $data 要发送的JSON数据
     * @param array $options 额外的请求选项
     * @return ResponseInterface 返回响应对象
     */
    public function json($url, $data = [], $options = [])
    {
        $options['json'] = $data;
        return $this->request('POST', $url, $options);
    }

    /**
     * 核心请求方法
     *
     * 处理所有HTTP请求的通用逻辑
     *
     * @param string $method HTTP请求方法(GET, POST等)
     * @param string $url 请求URL
     * @param array $options 请求选项
     * @return ResponseInterface 返回响应对象
     */
    private function request($method, $url, $options = [])
    {
        // 合并全局请求头与本次请求头
        $options['headers'] = array_merge(
            $this->headers,
            $options['headers'] ?? []
        );

        // 如果设置了代理,添加到请求选项中
        if (!empty($this->proxy)) {
            $options['proxy'] = $this->proxy;
        }

        return $this->client->request($method, $url, $options);
    }

    /**
     * 发送异步GET请求
     *
     * @param string $url 请求URL
     * @param array $options 请求选项
     * @return PromiseInterface 返回Promise对象
     */
    public function getAsync($url, $options = [])
    {
        return $this->requestAsync('GET', $url, $options);
    }

    /**
     * 发送异步POST表单请求
     *
     * @param string $url 请求URL
     * @param array $data POST表单数据
     * @param array $options 请求选项
     * @return PromiseInterface 返回Promise对象
     */
    public function postAsync($url, $data = [], $options = [])
    {
        $options['form_params'] = $data;
        return $this->requestAsync('POST', $url, $options);
    }

    /**
     * 发送异步JSON格式的POST请求
     *
     * @param string $url 请求URL
     * @param array $data 要发送的JSON数据
     * @param array $options 请求选项
     * @return PromiseInterface 返回Promise对象
     */
    public function jsonAsync($url, $data = [], $options = [])
    {
        $options['json'] = $data;
        return $this->requestAsync('POST', $url, $options);
    }

    /**
     * 核心异步请求方法
     *
     * 处理所有异步HTTP请求的通用逻辑
     *
     * @param string $method HTTP请求方法(GET, POST等)
     * @param string $url 请求URL
     * @param array $options 请求选项
     * @return PromiseInterface 返回Promise对象
     */
    private function requestAsync($method, $url, $options = [])
    {
        // 合并全局请求头与本次请求头
        $options['headers'] = array_merge(
            $this->headers,
            $options['headers'] ?? []
        );

        // 如果设置了代理,添加到请求选项中
        if (!empty($this->proxy)) {
            $options['proxy'] = $this->proxy;
        }

        return $this->client->requestAsync($method, $url, $options);
    }

    /**
     * 等待并解析多个异步请求
     *
     * 等待所有Promise完成并返回结果
     *
     * @param array $promises 异步请求Promise数组
     * @param bool $unwrap 是否展开结果(true返回响应内容,false返回Response对象)
     * @return array 返回请求结果数组
     */
    public function waitAll(array $promises, $unwrap = false)
    {
        $responses = Promise\Utils::unwrap($promises);

        if (!$unwrap) {
            return $responses;
        }

        $results = [];
        foreach ($responses as $key => $response) {
            $results[$key] = $response->getBody()->getContents();
        }

        return $results;
    }
}

/**
 * 使用示例:
 *
 * // 创建HttpClient实例
 * $httpClient = HttpClient::getInstance();
 *
 * // 发起多个异步请求
 * $promise1 = $httpClient->getAsync('https://api.example.com/data1');
 * $promise2 = $httpClient->getAsync('https://api.example.com/data2');
 * $promise3 = $httpClient->jsonAsync('https://api.example.com/submit', ['name' => 'test']);
 *
 * // 等待所有异步请求完成并获取结果
 * $results = $httpClient->waitAll([
 *     'data1' => $promise1,
 *     'data2' => $promise2,
 *     'submit' => $promise3
 * ], true);
 */

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 4

有什么意义呢?

1周前 评论
liuhaiqiang999 (楼主) 1周前

我记得guzzle本身是支持异步这些的。

1周前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!