0

0

PHP网络请求插件Guzzle使用

Guanhui

Guanhui

发布时间:2020-05-01 09:40:57

|

6398人浏览过

|

来源于jianshu

转载

在写后台代码时,避免不了需要与其他第三方接口交互,如向服务号下发模板消息,有时可能需要下发超过 10 万条。这时不得不考虑使用异步和「多线程」的网络请求。

今天向 PHP 工程师们推荐一个 Guzzle 插件。

Guzzle

Guzzle 是一个 PHP 的 HTTP 客户端,用来轻而易举地发送请求,并集成到我们的 WEB 服务上。

接口简单:构建查询语句、POST 请求、分流上传下载大文件、使用 HTTP cookies、上传 JSON 数据等等。

立即学习PHP免费学习笔记(深入)”;

发送同步或异步的请求均使用相同的接口。

使用 PSR-7 接口来请求、响应、分流,允许你使用其他兼容的 PSR-7 类库与 Guzzle 共同开发。

抽象了底层的 HTTP 传输,允许你改变环境以及其他的代码,如:对 cURL与 PHP 的流或 socket 并非重度依赖,非阻塞事件循环。

中间件系统允许你创建构成客户端行为。

安装 Guzzle

本文结合 Laravel 项目介绍 Guzzle 基本使用,所以使用 composer 来安装 Guzzle 再适合不过了,而且 Guzzle 官网也推荐使用 composer 来安装。

composer require guzzlehttp/guzzle:~6.0
// 或者
php composer.phar require guzzlehttp/guzzle:~6.0

发送简单的 POST 请求

访问第三方接口,基本上都是 POST 请求为主。如你想做一个简单的智能聊天工具,这时候可以借助图灵机器人 API,发送一个 POST 请求获取自动回答内容,直接上代码:

 '*****',
            'userid' => 'yemeishu'
        ];
        $params['info'] = $request->input('info', '你好吗');
        $client = new Client();
        $options = json_encode($params, JSON_UNESCAPED_UNICODE);
        $data = [
            'body' => $options,
            'headers' => ['content-type' => 'application/json']
        ];
        // 发送 post 请求
        $response = $client->post('http://www.tuling123.com/openapi/api', $data);
        $callback = json_decode($response->getBody()->getContents());
        return $this->output_json('200', '测试图灵机器人返回结果', $callback);
    }
}

Guzzle client->post 函数还是很简单的,只需要访问的接口,和请求的参数,参数中主要包含:body、headers、query等,具体可参考

http://guzzle-cn.readthedocs.io/zh_CN/latest/quickstart.html#id8

测试下:

6302-8a23f04d4eb24a12.jpg

6302-2f9f5585e3f021f6.jpg

Magic CMS 网站管理系统2.2.1.alpha 政企版
Magic CMS 网站管理系统2.2.1.alpha 政企版

Magic CMS网站管理系统(政企版)采用PHP+Mysql架构,再原CMS系统的基础上精简出适合企业政府客户使用版本,继承了原系统的快捷,高效,灵活,实用的特点,保留了核心功能,系统支持自定义模版(极易整合dede模板)、支持扩展插件,自定义模型等功能,保留了文章模型,视频模型,图集模型,产品模型,能够胜任企业多种建站需求。BUG修复:1.修改了程序安装时部分数据无法正常导入的错误2.修改了程

下载
注:图灵机器人还是很智能的,根据相同的 userid 能够识别上下文,做到智能聊天的。

发送异步的 POST 请求

在 PHP 开发中主要是「面向过程」式的开发方式,但请求第三方接口时,有时候并不需要等待第三方接口返回结果才继续执行。如用户购买成功时,我们需要向短信接口,发送一个 post 请求,由短信平台发送一条短信给用户,告知用户支付成功了,因为这类「提醒消息」属于「额外的附加功能」,并不需要在用户支付时「知道」有没有发送提醒成功。

这时候可以使用 Guzzle 的异步请求功能,直接看代码:

public function sms(Request $request) {
    $code = $request->input('code');
    $client = new Client();
    $sid = '9815b4a2bb6d5******8bdb1828644f2';
    $time = '20171029173312';
    $token = 'af8728c8bc*******12019c680df4b11c';

    $sig =  strtoupper(md5($sid.$token.$time));

    $auth = trim(base64_encode($sid . ":" . $time));

    $params = ['templateSMS' => [
            'appId' => '12b43**********0091c73c0ab',
            'param' => "coding01,$code,30",
            'templateId' => '3***3',
            'to' => '17689974321'
        ]
    ];
    $options = json_encode($params, JSON_UNESCAPED_UNICODE);
    $data = [
        'query' => [
            'sig' => $sig
        ],
        'body' => $options,
        'headers' => [
            'content-type' => 'application/json',
            'Authorization' => $auth
        ]
    ];

    // 发送 post 请求
    $promise = $client->requestAsync('POST', 'https://api.ucpaas.com/2014-06-30/Accounts/9815b4a2bb6d5******8bdb1828644f2/Messages/templateSMS', $data);

    $promise->then(
        function (ResponseInterface $res) {
            Log::info('---');
            Log::info($res->getStatusCode() . "\n");
            Log::info($res->getBody()->getContents() . "\n");
        },
        function (RequestException $e) {
            Log::info('-__-');
            Log::info($e->getMessage() . "\n");
        }
    );
    $promise->wait();

    return $this->output_json('200', '测试短信 api', []);
}

先返回接口数据:

6302-95ec6d7a688f1072.jpg

然后再输出 Log:

[2017-10-29 09:53:14] local.INFO: ---  
[2017-10-29 09:53:14] local.INFO: 200
  
[2017-10-29 09:53:14] local.INFO: {"resp":{"respCode":"000000","templateSMS":{"createDate":"20171029175314","smsId":"24a93f323c9*****8608568"}}}

最后收到短信信息:

微信截图_20200501093336.png

发送多线程异步 POST 请求

「发送多线程异步 POST 请求」在很多场合中使用到的,如:双十一快到了,可以做一些回馈老用户的活动,这是就需要批量的向老用户推送一条模板消息,告诉用户参与哪些活动的。这时候就需要用到多线程异步请求微信公众号接口。

直接上代码:

public function send($templateid, $openid, $url, $data) {
        $client = $this->bnotice->getHttp()->getClient();

        $requests = function ($open_ids) use ($templateid, $url, $data) {
            foreach($open_ids as $v){
                try {
                    yield $this->bnotice
                        ->template($templateid)
                        ->to($v)
                        ->url($url)
                        ->data($data)
                        ->request();
                } catch(Exception $e) {
                    Log::error('sendtemplate:'.$e->getMessage());
                }
            }
        };

        $pool = new Pool($client, $requests($openid), [
            'concurrency' => 16,
            'fulfilled' => function ($response, $index) {
            },
            'rejected' => function ($reason, $index) {
            },
        ]);

        $promise = $pool->promise();

        $promise->wait();
    }

其中 request 方法:

public function request($data = [])
    {
        $params = array_merge([
            'touser' => '',
            'template_id' => '',
            'url' => '',
            'topcolor' => '',
            'miniprogram' => [],
            'data' => [],
        ], $data);
        
        $required = ['touser', 'template_id'];

        foreach ($params as $key => $value) {
            if (in_array($key, $required, true) && empty($value) && empty($this->message[$key])) {
                throw new InvalidArgumentException("Attribute '$key' can not be empty!");
            }

            $params[$key] = empty($value) ? $this->message[$key] : $value;
        }

        $params['data'] = $this->formatData($params['data']);

        $this->message = $this->messageBackup;

        $options = json_encode ( $params,  JSON_UNESCAPED_UNICODE);
        $data = [
            'query' => [
                'access_token' => $this->getAccessToken()->getToken()
            ],
            'body' => $options,
            'headers' => ['content-type' => 'application/json']
        ];
        return function() use ($data) {
            return $this->getHttp()->getClient()->requestAsync('POST', $this::API_SEND_NOTICE, $data);
        };
    }

Guzzle 多线程异步请求原型函数,使用 GuzzleHttp\Pool 对象

use GuzzleHttp\Pool;use GuzzleHttp\Client;use GuzzleHttp\Psr7\Request;$client = new Client();$requests = function ($total) {
    $uri = 'http://127.0.0.1:8126/guzzle-server/perf';
    for ($i = 0; $i < $total; $i++) {
        yield new Request('GET', $uri);
    }};$pool = new Pool($client, $requests(100), [
    'concurrency' => 5,
    'fulfilled' => function ($response, $index) {
        // this is delivered each successful response
    },
    'rejected' => function ($reason, $index) {
        // this is delivered each failed request
    },]);// Initiate the transfers and create a promise$promise = $pool->promise();// Force the pool of requests to complete.$promise->wait();

总结

有了 Guzzle,极大方便了我们并发异步请求第三方接口。如果时间允许,我们可以看看 Guzzle 源代码,看看是如何实现的。

推荐教程:《PHP教程

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.7万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 7万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号