Home  >  Article  >  类库下载  >  Use the parallel method of PHP reloading and curl to elegantly encapsulate Xiaomi push SDK

Use the parallel method of PHP reloading and curl to elegantly encapsulate Xiaomi push SDK

高洛峰
高洛峰Original
2016-10-15 16:27:241652browse

Some time ago, we migrated some Xiaomi push code, which was previously the responsibility of others. After reading the code, I discovered two points:

The implementation of all interfaces is basically the same except for the url and parameters.

Android and ios devices need to be pushed once respectively.

I just learned about the concept of PHP reloading during this time. [Dynamic creation of types and methods is different from the concept of java and other parameters with different method names being the same. The specific concept can be RTFM] and the concurrency method of curl, so

For the first point above: Can we use the reuse of php? Load concept, use the magic method __call() to dynamically change the url parameters and request parameters of the interface call to implement calls to different interfaces pushed by Xiaomi. In other words, all our calling logic is implemented in the __call method. , but provides external calling methods for Xiaomi push to different interfaces, which will greatly simplify the code

For the second point above: Can we use the parallel mode of curl to push to android and ios devices at once, so that theoretically we can reduce The time of a push call, because we no longer need to wait for the push to one type of device to be pushed to another type of device

Next, we start to write code. First, construct a mipush entity. The member attributes of the entity include: the running environment, some initialized configuration parameters, and the information of the Xiaomi interface implemented (interface uri and parameters, etc.)

    /**
     * 运行环境 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'
                ],
            ]
        ],
    ];

The constructor of the mipush entity: implements a series of Configuration initialization

/**
     * 初始化配置
     * 
     * @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 entity’s magic method __call: dynamically implement parameter verification and calling of the Xiaomi push interface, so that we can implement a new Xiaomi push interface and implement configuration in the future.

/**
     * 魔术方法
     * 
     * 重载对象方法
     * @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);
        }
    }

After defining the Xiaomi push entity, we only need to use the mipush entity to instantiate and produce objects of different device types, and then use curl to initiate push in parallel.

/**
     * 并行推送
     * 
     * @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;
    }

That’s it. Through the above method, we have encapsulated a Xiaomi SDK with very little code. Currently, we only implement regid (registration id), alias (alias), user_account (user account), topic (label) ), multi_topic (multi-label), all (all) push.

How to use?

I haven’t published this on packagist yet. I published this on packagist. Interested students can google it by themselves, 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();
}


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Related articles

See more