mslib / remote-host

通用的Ms库,用于向API发送请求

1.2.0 2014-06-04 13:39 UTC

This package is not auto-updated.

Last update: 2024-09-28 15:51:15 UTC


README

此PHP库提供了一种简单的方法来向Web API发送请求。

系统要求

RemoteHost库需要PHP 5.3或更高版本。

PHP扩展

需要以下PHP扩展:

  • PHP Curl;

有关如何安装所有所需扩展的更多信息,请参阅它们的在线文档。

依赖项

RemoteHost库基于ZendFramework2。目前使用以下ZF2模块(有关所有依赖项的完整概述,请参阅composer.json):

{
    "require": {
        "zendframework/zend-http": "2.*",
        "zendframework/zend-config": "2.*",
        "zendframework/zend-json": "2.*",
        "zendframework/zend-uri": "2.*"
    }
}

该库仅针对使用Curl库发送的请求进行了测试。出于稳定性考虑,请确保所有使用此库配置的请求对象都是'Zend\Http\Client\Adapter\Curl'类的扩展(有关此类的更多详细信息,请参阅ZF2文档)。

安装

安装是一个简单的3步过程

  1. 使用composer下载RemoteHost
  2. 配置您的API调用
  3. 生成您的API实现

步骤1:使用composer下载RemoteHost

在您的composer.json中添加RemoteHost

{
    "require": {
        "mslib/remote-host": "dev-master"
    }
}

现在告诉composer下载库,运行以下命令

$ php composer.phar update mslib/remote-host

Composer将库安装到您的项目的vendor/mslib/remote-host目录。

步骤2:配置您的API调用

现在RemoteHost库已经在您的项目中可用(例如通过composer),您需要配置应用程序所需的所有API操作。

为了做到这一点,您需要创建一个包含一组指定配置键和值的数组的PHP文件。下面是此类文件的架构。

<?php

return array(
    'parameters' => array(
        'host'      => '', // (REQUIRED) The host api
        'port'      => '', // (optional) The port
        'user'      => '', // (optional) The user
        'password'  => '', // (optional) The password
    ),
    'actions_parameters' => array(
        // Add here all the parameters which are common to all actions. You still can override them by adding a different value in the parameters array of each action
        'key1' => 'value1',
        ...
    ),
    // For all possible values, please look at Zend\Http\Client->$config array
    'config' => array(
        'adapter'       => 'Zend\Http\Client\Adapter\Curl', // Please, leave this value for stability reason
        ...
    ),
    'actions' => array(
        'action-group' => array( // (REQUIRED) First Level Action Name 
            'action-name' => array( // (REQUIRED) Second Level Action Name 
                'name'              => '{API action name}', // (REQUIRED) the name of the action
                'request'           => array(
                    'adds_on'       => array( // Expressions to be added to the base url // e.g. 'name/protocol/entity/{id}/get
                        // here you can put as many adds on array as many you desire; they will be added to the base url in the given order
                        array(
                            'type'    => 'plain|replace', // the type of add on: 'plain' will simply concatenate the string given in the content field; 'replace' will first replace all parameter name within brackets '{{xxx}} and then concatenate it to the url
                            'content' => 'the content' // e.g. plain -> 'text-to-be-concatenated'; 'replace' => 'resource/{{id}}/get'
                        ),
                        array(
                            ...
                            ...
                        ),
                        ...
                        ...
                    ),
                    'headers'       => array( // Headers to be added to the requests with their default value
                        'header1' => 'default-value-1',
                        ...
                        ...
                    ),
                    'type'                     => 'Json|UrlEncoded|UrlEncodedFromContent|PlainText|Xml|{Custom Class Name with full namespace that extends class Msl\RemoteHost\Request\AbstractActionRequest}', // 'UrlEncoded', 'UrlEncodedFromContent', 'PlainText', 'Xml' and 'Json' are the request implementations available with the library
                    'method'                   => 'GET', // (optional) POST is the default value
                    'parameters'               => array( // (optional) array containing all request parameters (this array will be merged with the action_parameters defined above)
                        'key1' => 'value1', // put here a default value for each parameter; note that the default values will be overriden with the values passed in the execute method
                        ...
                    ),
                    'host'          => '', //(you can override here the general host; if left empty or not specified, the default value will be used)
                    'port'          => '', //(you can override here the general port; if left empty or not specified, the default value will be used)
                ),
                'response' => array(
                    'type'      => 'Json|PlainText|Xml|{Custom Class Name with full namespace that extends class Msl\RemoteHost\Response\AbstractActionResponse}', // (REQUIRED) Json, PlainText, Xml are the response implementations available with the library
                    'wrapper'   => '{Custom Class Name with full }', // (optional) if not specified, the default wrapper \Msl\RemoteHost\Response\Wrapper\DefaultResponseWrapper will be used
                ),
            ),
        ),

    ),
);

例如,假设您想向一个API发送请求,该API的基本URL为'http://www.example.com/api'。假设一个可用的操作名为'scripts',它返回服务器上所有可用的脚本列表。响应格式为Json或Xml,具体取决于请求参数'format'的值。请求方法为POST,请求参数应作为请求的一部分发送(即没有xml)。

此类函数的调用需要以下配置

<?php

return array(
    'parameters' => array(
        'host'      => 'http://www.example.com/api/', 
    ),
    'actions_parameters' => array(
    ),
    'config' => array(
        'maxredirects'  => 2,
        'timeout'       => 30,
        'adapter'       => 'Zend\Http\Client\Adapter\Curl',
    ),
    'actions' => array(
        'example-api' => array( 
            'script-list' => array( 
                'name'              => 'scripts',
                'adds-on'           => array(
                    array(
                        'type'    => 'plain',
                        'content' => 'scripts'
                    )
                ),
                'request'           => array(
                    'type'                     => 'UrlEncoded', 
                    'parameters'               => array( 
                        'format'      => 'json', 
                    ),
                ),
                'response' => array(
                    'type'      => 'Json', 
                ),
            ),
        ),
    ),
);

上述配置等同于发送一个具有以下参数的Curl请求

预期的响应类型为Json,它将被包装在库默认包装类'Msl\RemoteHost\Response\Wrapper\DefaultResponseWrapper'中。

有关响应包装器的更多详细信息,请参阅本文档的专用部分“内置响应包装器”。

有关所有配置键的更多详细信息,请参阅本文档的专用部分“配置键”。

步骤3:生成您的API实现

现在您已配置了所有必要的API操作,您需要在项目中创建一个类,该类扩展库RemoteHost中定义的基抽象类'Msl\RemoteHost\Api\AbstractHostApi'

'Msl\RemoteHost\Api\AbstractHostApi'类有一个抽象方法'getDefaultConfig()',因此应该在您的子类中实现此方法。此方法应返回步骤2中定义的数组的内容。

默认类构造函数需要两个参数

  • $apiName:在日志、异常等地方使用的API名称(例如 'MY_API');默认值由类常量 Msl\RemoteHost\Api\AbstractHostApi::API_NAME 定义;要覆盖此值,您可以在类构造函数中传递有效的字符串作为第一个参数,或者重新定义子类中的常量 API_NAME;
  • $config:包含步骤2中定义的配置的数组;

配置键

让我们更深入地看看上面描述的 步骤2:配置API调用。如前所述,为了配置您的API操作,您需要填写一个配置数组,其基本结构如下

<?php

return array(
    'parameters' => array(
        'host'      => '', // (REQUIRED) The host api
        'port'      => '', // (optional) The port
        'user'      => '', // (optional) The user
        'password'  => '', // (optional) The password
    ),
    'actions_parameters' => array(
        // Add here all the parameters which are common to all actions. You still can override them by adding a different value in the parameters array of each action
        'key1' => 'value1',
        ...
    ),
    // For all possible values, please look at Zend\Http\Client->$config
    'config' => array(
        'adapter'       => 'Zend\Http\Client\Adapter\Curl', // Please, leave this value for stability reason
        ...
    ),
    'actions' => array(
        'action-group' => array( // (REQUIRED) First Level Action Name
            'action-name-1' => array( // (REQUIRED) Second Level Action Name
                ...
            ),
            ...
            ...
            'action-name-N' => array( // (REQUIRED) Second Level Action Name
                ...
            ),
        ),

    ),
);

现在让我们更详细地看看每个配置块。

  • 'parameters'(必需):包含通用API主机连接参数的数组;
  • 'actions_parameters'(可选):包含所有配置操作共有的参数;您仍然可以通过在每个操作的参数数组中添加不同的值来覆盖它们,如以下专用段落中所述;
  • 'config'(必需):Zend Http Client类配置;出于稳定性的原因,请仅使用适配器 'Zend\Http\Client\Adapter\Curl',它是目前唯一经过测试的适配器;
  • 'actions'(必需):包含所有API操作的描述;更多详细信息可以在以下专用段落中找到;

'parameters'配置块

这是一个必需的块。如果在配置数组中没有指定'parameters'块,则将抛出'\Msl\RemoteHost\Exception\BadApiConfigurationException'异常;

该块由包含所有通用API主机连接参数的数组组成。当前版本支持以下参数

  • 'host'(必需):API主机URL(包括协议);
  • 'port'(可选):API主机端口;
  • 'user'(可选):API主机连接用户;
  • 'password'(可选):API主机连接密码;

唯一必需的参数是'host'。如果没有指定主机参数,则将抛出'\Msl\RemoteHost\Exception\BadApiConfigurationException'异常;

配置的'parameters'块示例如下

<?php

return array(
    'parameters' => array(
        'host'      => 'http://www.example.com/api',
        'port'      => '80',
        'user'      => 'testUser',
        'password'  => 'testPassword',
    ),
    ...
    ...
    ...
);

'actions_parameters'配置块

这不是一个必需的块。

该块由包含所有配置操作共有参数的数组组成。

假设您要配置N个共享一组给定参数的API调用。然后您可以在此指定此类参数及其默认值列表。

配置的'actions_parameters'块示例如下

<?php

return array(
    'parameters' => array(
        'host'      => 'http://www.example.com/api',
        'port'      => '80',
        'user'      => 'testUser',
        'password'  => 'testPassword',
    ),
    'actions_parameters' => array(
        'param1'    => 'default-value-1',
        'param2'    => 'default-value-2',
        ...
        ...
    )
    ...
    ...
);

'config'配置块

这是一个必需的块。如果在配置数组中没有指定'config'块,则将抛出'\Msl\RemoteHost\Exception\BadApiConfigurationException'异常;

该块由包含所有Zend Http Client类配置键的数组组成。有关所有可能值的完整列表,请参阅官方'Zend\Http\Client'文档或查看'Zend\Http\Client-$config'数组。

注意。出于稳定性的原因,请仅使用适配器'Zend\Http\Client\Adapter\Curl',它是目前唯一经过测试的适配器。

配置的'config'块示例如下

<?php

return array(
    ...
    ...
    'config' => array(
        'maxredirects'  => 2,
        'timeout'       => 30,
        'adapter'       => 'Zend\Http\Client\Adapter\Curl',
        ...
        ...
    )
    ...
    ...
);

'actions'配置块

这是一个必需的块。如果在配置数组中没有指定'actions'块,则将抛出'\Msl\RemoteHost\Exception\BadApiConfigurationException'异常;

此块包含一个数组,包含您希望从应用程序中调用的所有API操作。配置的 ‘actions’ 块的示例如下

<?php

return array(
    'parameters' => array(
        ...
    ),
    'actions_parameters' => array(
        ...
    ),
    'config' => array(
        ...
    ),
    'actions' => array(
        'action-group-1' => array( // (REQUIRED) First Level Action Name
            'action-name-1' => array( // (REQUIRED) Second Level Action Name
                'name'              => '{API action name}', // (REQUIRED) the name of the action
                'request'           => array(
                    'adds_on'       => array( // Expressions to be added to the base url // e.g. 'name/protocol/entity/{id}/get
                        ...
                    ),
                    'headers'       => array( // Headers to be added to the requests with their default value
                        ...
                    ),
                    'type'          => 'Json|UrlEncoded|UrlEncodedFromContent|PlainText|Xml|{Custom Class Name with full namespace that extends class Msl\RemoteHost\Request\AbstractActionRequest}', // 'UrlEncoded', 'UrlEncodedFromContent', 'PlainText', 'Xml' and 'Json' are the request implementations available with the library
                    'method'        => 'GET', // (optional) POST is the default value
                    'parameters'    => array( // (optional) array containing all request parameters (this array will be merged with the action_parameters defined above)
                        ...
                    ),
                    'host'          => '', //(you can override here the general host; if left empty or not specified, the default value will be used)
                    'port'          => '', //(you can override here the general port; if left empty or not specified, the default value will be used)
                ),
                'response' => array(
                    'type'      => 'Json|PlainText|Xml|{Custom Class Name with full namespace that extends class Msl\RemoteHost\Response\AbstractActionResponse}', // (REQUIRED) Json, PlainText, Xml are the response implementations available with the library
                    'wrapper'   => '{Custom Class Name with full }', // (optional) if not specified, the default wrapper \Msl\RemoteHost\Response\Wrapper\DefaultResponseWrapper will be used
                ),
            ),
            'action-name-2' => array(
                ...
                ...
            ),
        ),
        'action-group-2' => array(
            'action-name-1' => array(
                ...
                ...
            ),
            'action-name-2' => array(
                ...
                ...
            ),
        ),
    ),
);

每个配置的操作必须有两个操作名称级别。这允许按组对操作进行分组,以便更好地进行配置。在执行时间,每个配置的操作通过一个字符串来识别,该字符串是两个配置级别的连接(由 ‘.’ 分隔)。例如,通过查看上面的配置数组,名称为 ‘action-name-1’ 且组为 ‘action-group-1’ 的操作可以通过字符串 ‘action-group-1.action-name-1’ 来识别。

让我们来看看每个配置的操作的所有组件。

‘action’ 配置键

每个操作可用的配置键如下

  • ‘name’(必需):任意API操作名称;这是一个必需字段;
  • ‘request’(必需):一个数组,包含请求的所有必需配置(类型、方法、参数、头、URL附加等);这是一个必需字段;
  • ‘response’(必需):一个数组,包含响应的所有必需配置(类型和包装);这是一个必需字段;
‘request’ 配置键

在此子块中,您需要指定给定请求的所有必需配置键。更详细地说,可用的键有

  • ‘adds_on’(可选):一个数组,包含要添加到基础URL的所有可能的表达式;例如,‘name/protocol/entity/{id}/get;
  • ‘headers’(可选):一个数组,包含要添加到请求的所有头及其默认值;
  • ‘type’(必需):请求的类型;
  • ‘method’(可选):HTTP方法;当前版本支持GET、POST、PATCH、PUT和DELETE;这是一个可选参数;如果没有指定,将使用默认的‘POST’值;
  • ‘parameters’(可选):一个数组,包含所有请求参数及其默认值;此数组将与上面定义的 ‘action_parameters’ 合并;
  • ‘host’(可选):如果您想使用不同于通用的主机,您可以通过在此处指定它来实现;如果为空或未指定,将使用默认值(在全局配置中指定的值);
  • ‘port’(可选):如果您想使用不同于通用的端口,您可以通过在此处指定它来实现;如果为空或未指定,将使用默认值(在全局配置中指定的值);
‘adds_on’ 配置键

有两种可能的 'adds-on' 类型

  • 纯文本附加(简单连接到基础URL);
  • 替换附加(将某些变量替换为其内容后连接到基础URL);

每个 ‘adds_on’ 是一个数组,包含以下两个配置键

  • ‘type’(必需):类型;可能的值是:‘plain’和‘replace’,根据所需的附加类型;
  • ‘content’(必需):要添加到基础URL的内容;

如果您需要使用 ‘replace’ 附加,您可以在其内容中指定一个替换变量,通过以下字符包裹

{{ REPLACE_VARIABLE_NAME }}

'REPLACE_VARIABLE_NAME' 将作为具有要替换的附加内容中值的参数传递给 'execute()' 方法(在关联数组参数 '$urlBuildParameters' 中),如下所述。

以下是一个 adds_on 配置示例

<?php

return array(
    'parameters' => array(
        'host'      => 'http://www.example.com/api',
        ...
        ...
    ),
    ...
    ...
    'actions' => array(
        'action-group-1' => array(
            'action-name-1' => array(
                ...
                ...
                'request'           => array(
                    ...
                    ...
                    'adds_on'       => array(
                        array(
                            'type'    => 'plain',
                            'content' => 'url-added-plain-part'
                        ),
                        array(
                            'type'    => 'replace',
                            'content' => 'url-added-replace-part/{{id}}'
                        ),
                    ),
                    ...
                    ...
                ),
                ...
                ...
            ),
        ),
        ...
        ...
    ),
);

正如我们在第二个 adds_on 中所看到的,我们指定了将内容 'url-added-part/{{id}}' 添加到基本 URL,并将字符串 {{id}} 替换为传递给 'execute()' 方法的关联数组参数 '$urlBuildParameters' 的值,其中该条目的键为 'id',值为所需的值。

根据上述示例配置数组中指定的两个 adds_on,用于连接到 api 的最终 URL 将是

http://www.example.com/api/url-added-plain-part/url-added-replace-part/{{id}}

其中 {{id}} 将如上所述被 'execute()' 方法替换。

注意:所有指定的 adds_on 将按给定顺序添加到基本 URL。

'headers' 配置键

这是一个包含所有要添加到请求中的头部的关联数组。

以下是一个头部配置的示例

<?php

return array(
    ...
    ...
    'actions' => array(
        'action-group-1' => array(
            'action-name-1' => array(
                ...
                ...
                'request'           => array(
                    ...
                    ...
                    'headers'       => array( // Headers to be added to the requests with their default value
                        'Accept' => 'application/json',
                    ),
                    ...
                    ...
                ),
                ...
                ...
            ),
        ),
        ...
        ...
    ),
);

当调用 'execute()' 方法时,可以通过在关联数组参数 '$headersValue' 中指定配置头部的不同值来覆盖这些头部;在上面的例子中,为了覆盖默认头部 'Accept' => 'application/json',您必须传递以下数组作为数组参数 '$headersValue'

    array(
        'Accept' => 'text/xml',
    )
'type' 配置键

此配置键定义了所需的请求类型。库中已实现以下请求类型

  • 'UrlEncoded':用于发送带有某些参数编码在 URL 中的请求;
  • 'UrlEncodedFromContent':用于发送带有从给定请求文本内容中提取的编码参数的请求;
  • 'PlainText':用于发送带有纯文本内容类型的请求;
  • 'Xml':用于发送带有 XML 内容类型的请求;
  • 'Json':用于发送带有 JSON 内容类型的请求;

有关可用请求类型以及如何实现自定义请求的更多信息,请参阅本文件的 'BUILT-IN REQUESTS'

'response' 配置键

在此子块中,您需要指定给定操作的所需所有配置键。更详细地说,可用的键包括

  • ‘type’(必需):请求的类型;
  • 'wrapper'(可选):自定义包装器类名;如果未指定,则使用默认包装器 \Msl\RemoteHost\Response\Wrapper\DefaultResponseWrapper;
'type' 配置键

此配置键定义了所需的响应类型。库中已实现以下响应类型

  • 'PlainText':用于所有纯文本响应;
  • 'Xml':用于所有 XML 响应;
  • 'Json':用于所有 JSON 响应;

有关可用响应类型以及如何实现自定义响应的更多信息,请参阅本文件的 'BUILT-IN RESPONSES'

'wrapper' 配置键

包装器类是一个对象,由 'execute()' 方法返回,并包含从网络响应中提取的给定信息集。

有关可用包装器类以及如何实现自定义包装器类的更多信息,请参阅本文件的 'BUILT-IN RESPONSES'

BUILT-IN REQUESTS

所有由 'Msl\RemoteHost\Api\AbstractHostApi' 的实现发送的请求都将被包装在请求对象中,该对象扩展了抽象类 'Msl\RemoteHost\Request\AbstractActionRequest'。

'Msl\RemoteHost\Request\AbstractActionRequest' 是类 'Zend\Http\Request' 的扩展。

抽象行动请求类

AbstractActionRequest 实现了接口 'Msl\RemoteHost\Request\ActionRequestInterface',该接口定义了以下方法需要在子类中实现

  • init():初始化请求对象(设置请求类型、响应和响应包装类型、请求方法、基本 URL、端口等);
  • configure():配置动作请求(设置请求参数、内容、头部等);
  • setClientEncType():设置所需的编码方法;

AbstractActionRequest 类默认实现了 init() 方法,但没有实现 configure()setClientEncType() 方法。

内置请求对象

内置请求对象包括

  • UrlEncodedActionRequest:用于发送带有编码参数的请求;
  • UrlEncodedFromContentActionRequest:用于发送从给定请求文本内容中提取编码参数的请求;
  • XmlActionRequest:用于发送带有 XML 内容类型的请求;
  • PlainTextActionRequest:用于发送带有纯文本内容类型的请求;
  • JsonActionRequest:用于发送带有 JSON 内容类型的请求;

如果您必须发送内容需要在 URL 中编码的请求,请使用类型 UrlEncodedActionRequestUrlEncodedFromContentActionRequest。如果您想发送包含纯文本、XML 数据或 JSON 数据的请求体,请分别使用 PlainTextActionRequestXmlActionRequestJsonActionRequest

UrlEncoded 请求

UrlEncoded 请求对象可以用来发送带有请求中编码的参数的请求。

它支持 GET、POST、PUT、PATCH 和 DELETE HTTP 方法。

为了使用它,您需要在给定的配置动作的配置键 'request.type' 中使用标签 'UrlEncoded',如下所示

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'request'           => array(
                    'type' => 'UrlEncoded',
                    ...
                ),
                ...
            ),
        ),
    ),
);

UrlEncodedFromContent 请求

UrlEncodedFromContent 请求对象可以用来发送带有请求中编码的参数的请求,这些参数是从给定的文本内容中提取的。

它支持 GET、POST、PUT、PATCH 和 DELETE HTTP 方法。

为了使用它,您需要在给定的配置动作的配置键 'request.type' 中使用标签 'UrlEncodedFromContent',如下所示

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'request'           => array(
                    'type' => 'UrlEncodedFromContent',
                    ...
                ),
                ...
            ),
        ),
    ),
);

Xml 请求

Xml 请求对象可以用来发送带有 XML 内容的请求。它将自动添加以下头部到请求中

'Content-Type'=>'text/xml' 

它支持 GET、POST、PUT、PATCH 和 DELETE HTTP 方法。

为了使用它,您需要在给定的配置动作的配置键 'request.type' 中使用标签 'Xml',如下所示

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'request'           => array(
                    'type' => 'Xml',
                    ...
                ),
                ...
            ),
        ),
    ),
);

注意。如果您的请求体为空(例如请求参数编码在 URL 中),请不要使用此请求对象。请使用 UrlEncoded 代替!

PlainText 请求

PlainText 请求对象可以用来发送带有纯文本内容的请求。

它支持 GET、POST、PUT、PATCH 和 DELETE HTTP 方法。

为了使用它,您需要在给定的配置动作的配置键 'request.type' 中使用标签 'PlainText',如下所示

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'request'           => array(
                    'type' => 'PlainText',
                    ...
                ),
                ...
            ),
        ),
    ),
);

注意。如果您的请求体为空(例如请求参数编码在 URL 中),请不要使用此请求对象。请使用 UrlEncoded 代替!

Json 请求

Json 请求对象可以用来发送带有 JSON 内容的请求。它将自动添加以下头部到请求中

'Content-Type'=>'application/json' 

它支持 GET、POST、PUT、PATCH 和 DELETE HTTP 方法。

为了使用它,您需要在给定的配置动作的配置键 'request.type' 中使用标签 'Json',如下所示

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'request'           => array(
                    'type' => 'Json',
                    ...
                ),
                ...
            ),
        ),
    ),
);

注意。如果您的请求体为空(例如请求参数编码在 URL 中),请不要使用此请求对象。请使用 UrlEncoded 代替!

加载您的自定义请求对象

您也可以通过扩展基抽象类 'Msl\RemoteHost\Request\AbstractActionRequest' 来定义自己的请求对象,并在配置文件中使用它。

以下是一个自定义请求对象的类实现和配置文件。

<?php

namespace Msl\Example\Request;

class GoogleRequestActionRequest extends AbstractActionRequest
{
    /**
     * Configures an action request with the given request values and content
     *
     * @param array  $requestValues      the request parameters
     * @param string $content            the body content
     * @param array  $urlBuildParameters the url build adds on parameter array
     * @param array  $headersValue       the header value array to override default header values
     *
     * @return mixed|void
     *
     * @throws \Msl\RemoteHost\Exception\BadConfiguredActionException
     */
    public function configure(array $requestValues, $content = "", array $urlBuildParameters = array(), array $headersValue = array())
    {
        // Set request parameters in parent entity
        parent::configure($requestValues, $content, $urlBuildParameters, $headersValue);

        // Set the request body content
        $this->setContent($content);
    }

    /**
     * Sets a proper EncType on the given \Zend\Http\Client object (for Xml Request, used value is Client::ENC_URLENCODED)
     *
     * @param \Zend\Http\Client $client the Zend http client object
     *
     * @return mixed|\Zend\Http\Client
     */
    public function setClientEncType(\Zend\Http\Client $client)
    {
        // Setting EncType to UrlEncoded
        $client->setEncType(\Zend\Http\Client::ENC_URLENCODED);

        return $client;
    }
}

然后,您可以通过在给定的配置动作的配置键 'request.type' 中指定完整的类命名空间来使用您的自定义请求对象,如下所示

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'request'           => array(
                    'type' => 'Msl\Example\Request\GoogleRequestActionRequest',
                    ...
                ),
                ...
            ),
        ),
    ),
);

内置响应

所有由 'Msl\RemoteHost\Api\AbstractHostApi' 的实现接收到的响应都将被包装在响应对象中,该对象扩展了抽象类 'Msl\RemoteHost\Response\AbstractActionResponse'。

AbstractActionResponse 类

AbstractActionResponse 实现了接口 'Msl\RemoteHost\Response\ActionResponseInterface',该接口定义了以下方法需要在子类中实现:

  • setResponse():在给定的响应对象中设置 \Zend\Http\Response 对象;
  • setResponseWrapper():在给定的响应对象中设置 ResponseWrapperInterface 实现类(见下文对响应包装对象的解释);
  • bodyToArray():根据响应类型将响应体转换为数组(例如 json 转换为数组,xml 转换为数组,文本转换为数组等);
  • getParsedResponse():返回一个 ResponseWrapperInterface 实例;

AbstractActionResponse 类对方法 setResponse()setResponseWrapper()getParsedResponse() 提供了默认实现,但未提供对方法 bodyToArray() 的实现。

内置响应对象

内置响应对象包括:

  • JsonActionResponse:用于所有 Json 响应;
  • XmlActionResponse:用于所有 Xml 响应;
  • PlainTextActionResponse:用于所有纯文本响应;

Json 响应

当收到特定请求的 Json 响应时,可以使用 Json 响应对象。

为了使用它,您需要为配置动作的配置键 'response.type' 使用标签 'Json',如下所示:

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'response'           => array(
                    'type' => 'Json',
                    ...
                ),
                ...
            ),
        ),
    ),
);

Xml 响应

当收到特定请求的 Xml 响应时,可以使用 Xml 响应对象。

为了使用它,您需要为配置动作的配置键 'response.type' 使用标签 'Xml',如下所示:

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'response'           => array(
                    'type' => 'Xml',
                    ...
                ),
                ...
            ),
        ),
    ),
);

纯文本响应

当收到特定请求的纯文本响应时,可以使用纯文本响应对象。

为了使用它,您需要为配置动作的配置键 'response.type' 使用标签 'PlainText',如下所示:

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'response'           => array(
                    'type' => 'PlainText',
                    ...
                ),
                ...
            ),
        ),
    ),
);

加载您的自定义响应对象

您也可以通过扩展基本抽象类 'Msl\RemoteHost\Response\AbstractActionResponse' 来定义自己的响应对象,并在配置文件中使用它。

以下是一个自定义响应对象的类实现和配置文件示例。

<?php

namespace Msl\Example\Request;

class GoogleResponseActionResponse extends AbstractActionResponse
{
    /**
     * Converts the Response object body to an array
     *
     * @return array
     */
    public function bodyToArray()
    {
        // Getting response content
        $responseContent = $this->response->getContent();

        // We parse the content in a custom way and we convert it to an array...
        $customContentAsArray = array();

        ...........
        ...........
        ...........

        return $customContentAsArray;
    }
}

您可以通过在配置动作的配置键 'response.type' 中指定完整的类命名空间来使用您的自定义响应对象,如下所示:

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'response'           => array(
                    'type' => 'Msl\Example\Response\GoogleResponseActionResponse',
                    ...
                ),
                ...
            ),
        ),
    ),
);

内置响应包装器

包装器类是一个对象,由 'execute()' 方法返回,并包含从网络响应中提取的给定信息集。

此信息可能包括:

  • 响应状态:如果请求成功则为 true;否则为 false;
  • 响应返回代码:内部或一般返回代码(例如 HTTP 状态代码);
  • 与找到的返回代码关联的响应返回消息:内部或一般返回消息(例如 HTTP 状态消息);
  • 响应体:响应体的数组表示;

所有响应包装器对象都应扩展基本抽象类 'Msl\RemoteHost\Response\Wrapper\AbstractResponseWrapper',该类实现了接口 'Msl\RemoteHost\Response\Wrapper\ResponseWrapperInterface'

默认响应包装器

如果您未在配置键 'response.wrapper' 中定义响应包装器,则将使用默认包装器 \Msl\RemoteHost\Response\Wrapper\DefaultResponseWrapper。

此包装器对象包含以下信息:

  • 响应状态:如果 HTTP 状态码等于 200、201、202 或 204,则为 true;否则为 false;
  • 响应返回代码:从远程 API 收到的响应中的 HTTP 状态码(例如 200、201、404 等);
  • 响应返回消息:从远程 API 收到的响应中的 HTTP 状态消息(例如 OK、Created、Accepted、Not Found 等);
  • 响应体:从远程 API 收到的响应体的数组表示;

加载您的自定义响应包装器对象

您也可以通过扩展基本抽象类 'Msl\RemoteHost\Response\Wrapper\AbstractResponseWrapper' 来定义自己的响应包装器对象,并在配置文件中使用它。

以下是一个自定义响应包装对象的一个类实现和一个配置文件。

<?php

use Msl\RemoteHost\Response\Wrapper\AbstractResponseWrapper;

/**
 * Json Google Response Wrapper for Google Actions
 */
class JsonGoogleResponseWrapper extends AbstractResponseWrapper
{
    /**
     * Defaults status strings
     */
    const STATUS_OK = "OK";

    /**
     * Initializes the object fields with the given raw data.
     *
     * @param array                    $rawData        array containing the response raw data
     * @param ActionResponseInterface  $actionResponse the action response object from which to extract additional information
     *
     * @return mixed
     */
    public function init(array $rawData, ActionResponseInterface $actionResponse)
    {
        // Setting raw data field
        $this->rawData = $rawData;

        // Setting status
        if (is_array($rawData) && isset($rawData['status'])) {
            if ($rawData['status'] === self::STATUS_OK) {
                $this->status = true;
            } else {
                $this->status = false;
            }
        } else {
            $this->status = false;
        }

        // Setting return code and return message
        $response = $actionResponse->getResponse();
        $this->returnCode    = $response->getStatusCode();
        $this->returnMessage = $response->getReasonPhrase();
    }

    /**
     * Returns the found routes
     *
     * @return array
     */
    public function getRoutes()
    {
        return $this->getBody();
    }

    /**
     * Return the body of the Response.
     *
     * @return array
     */
    public function getBody()
    {
        if (isset($this->rawData['routes'])) {
            return $this->rawData['routes'];
        }
        return array();
    }
}

然后,您可以通过指定配置键 'response.wrapper' 中的完整类命名空间来使用您的自定义响应包装对象,如下所示:

<?php

return array(
    'parameters' => array(
        ...
    ),
    ...
    'actions' => array(
        'example-api' => array(
            'action-1' => array(
                'name'              => 'scripts',
                'response'           => array(
                    'type'    => 'Json',
                    'wrapper' => 'Connector\Api\Google\ResponseWrapper\JsonGoogleResponseWrapper',
                ),
                ...
            ),
        ),
    ),
);

基本使用

调用配置了的动作

一旦您配置了所有必需的动作并且您已经创建了一个扩展基本抽象类 'Msl\RemoteHost\Api\AbstractHostApi' 的 API 类,您就可以开始发送请求。

为此,您必须使用自定义 API 类的 execute() 方法,该方法需要以下参数:

  • $actionName:要执行的动作名称(必需);
  • $requestParameters:在动作执行中使用的请求参数(键/值)(可选 -> 默认值为空数组);
  • $content:要设置在请求体中的内容(可选 -> 默认值为空字符串);
  • $urlBuildParameters:url 构建添加的参数数组;
  • $headersValue:要覆盖默认头部值的头部值数组;

第一个参数 $actionName 与通过连接配置数组 actions 中配置的所需动作的两个配置级别(由 '.' 分隔)得到的字符串相对应。

例如,考虑以下配置

<?php

return array(
    'parameters' => array(
        'host'      => 'http://www.example.com/api/', 
    ),
    'actions_parameters' => array(
    ),
    'config' => array(
        'maxredirects'  => 2,
        'timeout'       => 30,
        'adapter'       => 'Zend\Http\Client\Adapter\Curl',
    ),
    'actions' => array(
        'example-api' => array( 
            'script-list' => array( 
                'name'              => 'scripts', 
                'request'           => array(
                    'type'                     => 'UrlEncoded', 
                    'parameters'               => array( 
                        'format'      => 'json', 
                    ),
                ),
                'response' => array(
                    'type'      => 'Json', 
                ),
            ),
        ),
    ),
);

为了发送请求给以下子数组配置的动作

<?php

return array(
    ...
    ...
    'actions' => array(
        'example-api' => array( 
            'script-list' => array( 
                ...
                ...
            ),
        ),
    ),
    ...
    ...    
);

您必须将以下字符串作为 execute() 方法的第一个参数传递

example-api.script-list

因此,要使用默认参数(如配置数组中配置的)调用动作 example-api.script-list,您必须在我们的代码中使用以下行

<?php      
    ...
    ...
    // ApiImplementation is a child class of Msl\RemoteHost\Api\AbstractHostApi
    $api = new ApiImplementation();
    
    // Calling action script-list
    $result = $api->execute('example-api.script-list');
    ...
    ...    

使用一些特定参数调用配置了的动作

如果您需要使用一些特定参数调用给定的配置了动作,那么您必须将这些值放入关联数组中,并将其作为 execute() 函数的第二个参数传递,如下所示

<?php        
    ...
    ...
    // ApiImplementation is a child class of Msl\RemoteHost\Api\AbstractHostApi
    $api = new ApiImplementation();
        
    // Creating parameters array: here we can override all the default parameters defined in the configuration array
    $parameters = array('format'=>'xml');
    
    // Calling action script-list
    $result = $api->execute('example-api.script-list', $parameters);

使用一些特定请求体内容调用配置了的动作

如果您需要使用一些特定请求体内容调用给定的配置了动作,那么您必须将此类内容作为 execute() 函数的第三个参数传递,如下所示

<?php
    ...
    ...
    // ApiImplementation is a child class of Msl\RemoteHost\Api\AbstractHostApi
    $api = new ApiImplementation();
        
    // Creating parameters array: here we can override all the default parameters defined in the configuration array
    $parameters = array();
    
    // Creating request content: this could be an XML content for example
    $content = 'text content';
    
    // Calling action script-list
    $result = $api->execute('example-api.script-list', $parameters, $content);

使用一些 URL 附加参数调用配置了的动作

如果您需要使用一些特定请求体内容调用给定的配置了动作,那么您必须将此类内容作为 execute() 函数的第三个参数传递,如下所示

<?php
    ...
    ...
    // ApiImplementation is a child class of Msl\RemoteHost\Api\AbstractHostApi
    $api = new ApiImplementation();

    // Creating parameters array: here we can override all the default parameters defined in the configuration array
    $parameters = array();

    // Creating request content: this could be an XML content for example
    $content = 'text content';

    // Calling action script-list
    $result = $api->execute('example-api.script-list', $parameters, $content);

使用一些特定头部值调用配置了的动作

如果您需要使用一些特定请求体内容调用给定的配置了动作,那么您必须将此类内容作为 execute() 函数的第三个参数传递,如下所示

<?php
    ...
    ...
    // ApiImplementation is a child class of Msl\RemoteHost\Api\AbstractHostApi
    $api = new ApiImplementation();

    // Creating parameters array: here we can override all the default parameters defined in the configuration array
    $parameters = array();

    // Creating request content: this could be an XML content for example
    $content = 'text content';

    // Calling action script-list
    $result = $api->execute('example-api.script-list', $parameters, $content);

GoogleApi 实现示例

有关如何使用此库的完整示例,请参阅 'mslib/directions-demo' 存储库,该存储库实现了 Google Maps API 的 API 连接层。

以下是前面提到的示例存储库的简要说明。

假设您想实现一个封装所有 Google API 调用的类。为此,您需要创建一个扩展基本抽象类 'Msl\RemoteHost\Api\AbstractHostApi' 的类,并为其定义一个配置。

让我们从以下 URL 中记录的 Google API 函数 'directions' 的实现开始

https://developers.google.com/maps/documentation/directions/?hl=en

配置

假设您想使用以下配置实现对 Google API 的 'directions' 的调用

请求 URL 示例如下:[http://maps.googleapis.com/maps/api/directions/json?origin=Toronto&destination=Montreal&sensor=false]

此类调用的配置如下

<?php

return array(
    'parameters' => array(
        'host'      => 'http://maps.googleapis.com/maps/api/', // The host api
    ),
    'actions_parameters' => array(
    ),
    // For all possible values, please look at Zend\Http\Client->$config
    'config' => array(
        'maxredirects'  => 2,
        'timeout'       => 30,
        'adapter'       => 'Zend\Http\Client\Adapter\Curl',
    ),
    'actions' => array(
        'google-json' => array(
            'driving-directions' => array(
                'name'              => 'directions/json',
                'request'           => array(
                    'adds_on'       => array(
                        array ( // (e.g. http://maps.googleapis.com/maps/api/directions/json)
                            'type'    => 'plain',
                            'content' => 'directions/json'
                        )
                    ),
                    'type'                     => 'UrlEncoded',
                    'method'                   => 'GET', 
                    'parameters'               => array( 
                        'origin'      => '', // default value for each parameter; default values will be overriden with the values passed in the execute method
                        'destination' => '',
                        'sensor'      => '',
                    ),
                ),
                'response' => array(
                    'type'      => 'Json', 
                ),
            ),
        ),
    ),
);

API 类

现在你已经为'destinations' API调用准备好了配置,你需要实现我们的API类,这个类将负责连接到远程API并发送请求。

为此,你应该实现一个名为'GoogleApi'的类,它如下扩展了基类'Msl\RemoteHost\Api\AbstractHostApi'

<?php

class GoogleApi extends AbstractHostApi
{
    /**
     * String containing the name of this api. This value will be used mainly for log purposes.
     *
     * @var string
     */
    const API_NAME = 'GOOGLE_API';

    /**
     * Returns the default config array
     *
     * @return mixed
     */
    public function getDefaultConfig()
    {
        return include __DIR__ . '/resources/config/googlehost.config.php';
    }    
}

请注意:

  • 你已经实现了父抽象方法'getDefaultConfig',该方法应返回上一步定义的配置数组。假设这样的数组存储在一个文件中,该文件的路径是'/resources/config/googlehost.config.php'。
  • 你已经重新定义了常量'API_NAME',使其包含值'GOOGLE_API';这可能对日志记录很有用;

API方法

最后一步是在'GoogleApi'类中定义一个方法,这样你就可以在方法中包装对配置操作'google-json.driving-directions'的调用。为此,你应该添加一个名为'getRoutes()'的方法,如下所示

<?php

namespace Connector\Api\Google;

use Msl\RemoteHost\Api\AbstractHostApi;

class GoogleApi extends AbstractHostApi
{
    /**
     * String containing the name of this api. This value will be used mainly for log purposes.
     *
     * @var string
     */
    const API_NAME = 'GOOGLE_API';

    /**
     * Returns the default config array
     *
     * @return mixed
     */
    public function getDefaultConfig()
    {
        return include __DIR__ . '/resources/config/googlehost.config.php';
    }

    /**
     * A Directions API request
     *
     * @param string $origin      The address or textual latitude/longitude value from which you wish to calculate directions
     * @param string $destination The address or textual latitude/longitude value from which you wish to calculate directions
     * @param string $sensor      whether or not the directions request comes from a device with a location sensor
     *
     * @return \Msl\RemoteHost\Response\AbstractResponseWrapper
     */
    public function getRoutes($origin, $destination, $sensor)
    {

        /** @var /ResponseWrapper/JsonGoogleResponseWrapper $response */
        $response = null;
        try {
            $response = $this->execute(
                'google-json.driving-directions',
                array(
                    'origin'      => $origin,
                    'destination' => $destination,
                    'sensor'      => $sensor,
                )
            );
        } catch (\Exception $e) {
            echo sprintf('[%s] Google Host call failed! Error message is: \'%s\'', $this->getApiName(), $e->getMessage());
        }

        return $response;
    }
}

如你所见,此方法有三个参数:起点、终点和传感器。这些参数对应于Google API调用所需的起点、终点和传感器参数,如Google API文档中对于动作'directions'所述。