0

0

利用php重载和curl的并行方式优雅的封装小米推送sdk

高洛峰

高洛峰

发布时间:2016-10-15 16:27:24

|

1859人浏览过

|

来源于php中文网

原创

前段时间迁移小米推送部分代码,这部分之前是其他人负责的。读了代码,发现了两点:

所有接口的实现除了url和传参基本都是一致的

android和ios的设备需要分别推送一次

刚好这段时间了解了一下php的重载概念【动态的创建类属型和方法,不同于java等的参数不同方法名相通的概念,具体的概念可以RTFM】和curl的并发方式,所以

对于以上第一点:是否可以利用php的重载概念,用魔术方法__call()动态的变更接口调用的url参数和请求参数,去实现对小米推送不同接口的调用,也就是说我们所有的调用逻辑都是实现在__call这一个方法中,却对外提供小米推送不同接口的调用方法,这样就会极大的简化代码

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

对于以上第二点:是否可以利用curl的并行方式一次性推送给android和ios设备,这样理论上我们可以减少一次推送调用的时间,因为我们不需要再去等待给一类设备推送完了,再去推送给另一类设备

飞书妙记
飞书妙记

飞书智能会议纪要和快捷语音识别转文字

下载

接下来,我们开始造代码。首先,构造一个mipush的实体,实体的成员属性包括:运行环境、初始化的一些配置参数、所实现的小米接口的信息(接口uri和参数等)

    /**
     * 运行环境 develop:开发环境 product:生产环境
     * @var string
     */
    private $_environment = 'develop';

    /**
     * 设备系统类型 android ios
     * @var string
     */
    private $_osType      = '';

    /**
     * 小米推送域名
     * @var string
     */
    private $_host        = '';

    /**
     * 请求头
     * @var string
     */
    private $_headers     = '';

    /**
     * 接口url
     * @var string
     */
    private $_url         = '';

    /**
     * 调用的接口方法名称
     * @var array
     */
    private $_function    = [];

    /**
     * 请求参数
     * @var array
     */
    private $_data        = [];

    /**
     * 小米推送设置
     * @var array
     */
    private $_options = [
        'title'                   => '消息通知自定义title',
        'restricted_package_name' => '',
        'pass_through'            => 0, // 0 通知栏消息 1 透传
        'notify_type'             => -1, // -1:默认所有,1:使用默认提示音提示,2:使用默认震动提示,4:使用默认led灯光提示
        'time_to_send'             => 0, // 定时推送 单位毫秒 默认0
    ];

    /**
     * 运行环境配置
     * @var array
     */
    private static $_environmentConfig = [
        'domain' => [
            'product'  => 'https://api.xmpush.xiaomi.com/',
            'develop'  => 'https://sandbox.xmpush.xiaomi.com/'
        ],
    ];

    /**
     * 小米推送接口信息定义
     * 
     * url/请求参数
     * @var array
     */
    private $_functionDefine = [
        'regid' => [
            'uri' => 'v3/message/regid',
            'arguments' => [
                'registration_id' => [
                    'type' => 'array',
                    'must' => 'y'
                ],
                'description' => [
                    'type' => 'string',
                    'must' => 'y'
                ],
                'params' => [//自定义参数
                    'type' => 'array',
                    'must' => 'n'
                ],
            ]
        ],
        'userAccount' => [
            'uri' => 'v2/message/user_account',
            'arguments' => [
                'user_account' => [
                    'type' => 'array',
                    'must' => 'y'
                ],
                'description' => [
                    'type' => 'string',
                    'must' => 'y'
                ],
                'params' => [//自定义参数
                    'type' => 'array',
                    'must' => 'n'
                ],
            ]
        ],
        'alias' => [
            'uri' => 'v3/message/alias',
            'arguments' => [
                'alias' => [
                    'type' => 'array',
                    'must' => 'y'
                ],
                'description' => [
                    'type' => 'string',
                    'must' => 'y'
                ],
                'params' => [//自定义参数
                    'type' => 'array',
                    'must' => 'n'
                ],
            ]
        ],
        'topic' => [
            'uri' => 'v3/message/topic',
            'arguments' => [
                'topics' => [
                    'type' => 'array',
                    'must' => 'y'
                ],
                'description' => [
                    'type' => 'string',
                    'must' => 'y'
                ],
                'params' => [//自定义参数
                    'type' => 'array',
                    'must' => 'n'
                ],
            ]
        ],
        'multiTopic' => [
            'uri' => 'v3/message/multi_topic',
            'arguments' => [
                'topics' => [
                    'type' => 'array',
                    'must' => 'y'
                ],
                'topics_op' => [// UNION并集,INTERSECTION交集,EXCEPT差集
                    'type' => 'string',
                    'must' => 'y'
                ],
                'description' => [
                    'type' => 'string',
                    'must' => 'y'
                ],
                'params' => [//自定义参数
                    'type' => 'array',
                    'must' => 'n'
                ],
            ]
        ],
        'all' => [
            'uri' => 'v3/message/all',
            'arguments' => [
                'description' => [
                    'type' => 'string',
                    'must' => 'y'
                ],
                'params' => [//自定义参数
                    'type' => 'array',
                    'must' => 'n'
                ],
            ]
        ],
    ];

mipush实体的构造函数:实现对一系列配置的初始化

/**
     * 初始化配置
     * 
     * @param $string $os_type 系统类型
     * @param $string $config  配置
     * @param array   $options 设置 [
     *                        'title'        => 'string,标题', 
     *                        'pass_through' => 'tinyint,0通知栏消息,1透传,默认0'
     *                        'notify_type'  => 'tinyint,-1,1,2,3,4',
     *                        'time_to_send' => 'int, 定时推送, 毫秒'
     *                        ]
     * @param string  $environment 环境
     */
    public function __construct($os_type='', $config=array(), $options=array(), $environment='')
    {
        /* init environment */
        if ($environment) {
            $this->_environment = $environment;
        }
        if ($os_type === 'ios') {
            $this->_host     = self::$_environmentConfig['domain'][$this->_environment];// ios
        }else{
            $this->_host     = self::$_environmentConfig['domain']['product'];// android
        }
        
        /* init option */
        $this->_headers   = [];
        $this->_headers[] = 'Authorization: key=' . $config['secret'];
        if ($os_type === 'android') {
            $this->_options['restricted_package_name'] = $config['package_name'];
        }
        foreach ($this->_options as $k => &$v) {
            if (in_array($k, $options)) {
                $v = $options[$k];
            }
        }
    }

mipush实体的魔法方法__call:动态实现对小米推送接口的参数验证和调用,以至于我们未来实现新的小米推送接口及实现配置就可以。

/**
     * 魔术方法
     * 
     * 重载对象方法
     * @param  string $name      小米推送方法名称
     * @param  array  $arguments 请求参数
     * @return mixed             void||object
     */
    public function __call($name,$arguments)
    {
        $arguments = $arguments[0];
        $this->_function = $this->_functionDefine[$name];
        $this->_url = $this->_host . $this->_function['uri'];
        $this->dataCheck($arguments);

        switch ($name) {
            case 'regid':
                $this->_data['registration_id'] = $arguments['registration_id'];
                break;
            case 'userAccount':
                $this->_data['user_account'] = implode(',', $arguments['user_account']);
                break;
            case 'alias':
                $this->_data['alias']        = implode(',', $arguments['alias']);
                break;
            case 'topic':
                $this->_data['topic']        = $arguments['topic'];
                break;
            case 'multiTopic':
                $this->_data['topics']       = implode(";$;", $arguments['topics']);
                $this->_data['topic_op']     = $arguments['topic_op'];
                break;
            case 'all':
                $this->_data['topics']       = implode(";$;", $topics);
                $this->_data['topic_op']     = 'UNION';
                break;
                
                default:
                throw new \Exception('Sorry, This function is useless in this version', 404);
                break;
        }

        $this->_data['description']  = $arguments['description'];
        if($arguments['params']) {
            foreach ($arguments['params'] as $k => $v) {
                $this->_data['extra.'.$k] = $v;// 自定义参数
            }
        }
        if ($this->_osType === 'android') {
            $this->_data = array_merge($this->_data, $this->_options);
        }
    }

定义完小米推送实体后,我们只需要通过mipush这个实体,实例化生产不同设备类型的对象,再由curl并行的方式发起推送即可。

/**
     * 并行推送
     * 
     * @param  Mipush $mipush_ios     ios端实体
     * @param  Mipush $mipush_android android端实体
     * @return array                  推送结果
     */
    private static function curlRequest(Mipush $mipush_ios, Mipush $mipush_android) 
    {
        $ch_ios     = curl_init();
        $ch_android = curl_init();
        curl_setopt($ch_ios, CURLOPT_URL, $mipush_ios->_url);
        curl_setopt($ch_ios, CURLOPT_POST, 1);
        curl_setopt($ch_ios, CURLOPT_POSTFIELDS, $mipush_ios->_data);
        curl_setopt($ch_ios, CURLOPT_HTTPHEADER, $mipush_ios->_headers);
        curl_setopt($ch_ios, CURLOPT_RETURNTRANSFER, 1); 
        
        curl_setopt($ch_android, CURLOPT_URL, $mipush_android->_url);
        curl_setopt($ch_android, CURLOPT_POST, 1);
        curl_setopt($ch_android, CURLOPT_POSTFIELDS, $mipush_android->_data);
        curl_setopt($ch_android, CURLOPT_HTTPHEADER, $mipush_android->_headers);
        curl_setopt($ch_android, CURLOPT_RETURNTRANSFER, 1); 
        
        $mh = curl_multi_init();
        curl_multi_add_handle($mh, $ch_ios);
        curl_multi_add_handle($mh, $ch_android);

        $running=null;
        do {
           curl_multi_exec($mh,$running);
        } while($running > 0);

        $result['ios']        = json_decode(curl_multi_getcontent($ch_ios), true);
        $result['android'] = json_decode(curl_multi_getcontent($ch_android), true);

        curl_multi_remove_handle($mh, $ch_ios);
        curl_multi_remove_handle($mh, $ch_android);
        curl_multi_close($mh);
        return $result;
    }

以上就是这些了,通过以上的方式我们就用很少的代码封装了一个小米sdk,目前只实现了按regid(登记id),alias(别名),user_account(用户账号),topic(标签), multi_topic(多标签),all(全体)推送。

如何使用?

还没发布过packagist,我把这个发布到了packagist,有兴趣的同学可以自行google,haha~

composer require tigerb/easy-mipush

使用格式:
try {
    Push::init(
        ['secret' => 'string,必传,ios密钥'], 
        ['secret' => 'string,必传,android密钥', 'package_name' => 'string,必传,android包名']
        [   
          'title'        => 'string,非必传,消息通知自定义title',
          'pass_through' => 'int,非必传,0通知栏消息,1透传,默认0',
          'notify_type'  => 'int,非必传,-1:默认所有,1:使用默认提示音提示,2:使用默认震动提示,4:使用默认led灯光提示',
          'time_to_send' => 'int,非必传,定时推送,单位毫秒,默认0',
        ],
        'string,develop开发环境,product生产环境, 默认develop'
        );  
    $res = Push::toUse('string,小米push方法名', 'array, 该方法对应的参数');
    echo json_encode($res, JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
    echo $e->getMessage();
}

使用示例:
use Mipush\Push;

require './vendor/autoload.php';

try {
    Push::init(
        ['secret' => 'test'], 
        ['secret' => 'test', 'package_name' => 'com.test'],
        [   
          'title'        => 'test',
          'pass_through' => 0,
          'notify_type'  => -1,
          'time_to_send' => 0,
        ],
        'develop'
        );  
    $res = Push::toUse('userAccount', [
            'user_account' => [1],
            'description'  => 'test'
        ]);
    echo json_encode($res, JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
    echo $e->getMessage();
}
数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

17

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

3

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

14

2026.01.28

php怎么写接口教程
php怎么写接口教程

本合集涵盖PHP接口开发基础、RESTful API设计、数据交互与安全处理等实用教程,助你快速掌握PHP接口编写技巧。阅读专题下面的文章了解更多详细内容。

1

2026.01.28

php中文乱码如何解决
php中文乱码如何解决

本文整理了php中文乱码如何解决及解决方法,阅读节专题下面的文章了解更多详细内容。

3

2026.01.28

Java 消息队列与异步架构实战
Java 消息队列与异步架构实战

本专题系统讲解 Java 在消息队列与异步系统架构中的核心应用,涵盖消息队列基本原理、Kafka 与 RabbitMQ 的使用场景对比、生产者与消费者模型、消息可靠性与顺序性保障、重复消费与幂等处理,以及在高并发系统中的异步解耦设计。通过实战案例,帮助学习者掌握 使用 Java 构建高吞吐、高可靠异步消息系统的完整思路。

4

2026.01.28

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

23

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

122

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

51

2026.01.26

热门下载

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

精品课程

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

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