runet-id/api-client

RUNET-ID API 客户端


README

GitHub license Travis branch Codecov branch Packagist Packagist Pre Release

RUNET-ID API 文档

安装

执行安装包。

$ composer require runet-id/api-client:^3.0@beta php-http/discovery guzzlehttp/psr7 php-http/guzzle6-adapter

php-http/discovery 用于快速启动。稍后可以替换为显式的 HTTP 客户端和 PSR-7 工厂注入。更多详情请参阅 删除 Discovery 库 部分。

除了 guzzlehttp/psr7,您还可以使用 任何 PSR-7 消息实现,例如,zendframework/zend-diactoros

除了 php-http/guzzle6-adapter,您还可以使用 任何 HTTP 客户端实现,例如,cURL clientSocket client

使用方法

<?php

use Http\Discovery\MessageFactoryDiscovery;
use RunetId\Client\RunetIdClientFactory;
use RunetId\Client\Result\SuccessResult;

$factory = new RunetIdClientFactory();
$client = $factory->create('key', 'secret');

// Запрос с использованием встроенных подсказок по endpoint-ам RUNET-ID.
$user = $client->userGet()
    // метод setLanguage доступен во всех endpoint-ах
    ->setLanguage('en')
    ->setRunetId(1)
    ->getResult();

// Метод getResult возвращает размеченный phpDoc-свойствами класс.
$runetId = $user->RunetId;
$company = $user->Work->Company->Name;

// Чтобы получить исходный массив, используйте метод getRawResult.
$arrayUser = $client->userGet()
    ->setRunetId(1)
    ->getRawResult();

// Endpoint-ы можно использовать повторно.
$roleChanger = $client
    ->eventChangeRole()
    ->setRoleId(1);

$success1 = $roleChanger
    ->setRunetId(1)
    ->getResult()
    ->Success;

$success2 = $roleChanger
    ->setRunetId(2)
    ->getResult()
    ->Success;

// Данные можно передавать в свободной форме.
$company = $client
    ->companyGet()
    // Метод setQueryData() перезаписывает все параметры.
    ->setQueryData([
        'CompanyId' => 1,
    ])
    // Метод addQueryData() добавляет параметры, используя array_merge().
    ->addQueryData([
        'Language' => 'en',
    ])
    // Метод setQueryValue() устанавливает значение конкретного параметра,
    // перезаписывая предыдущее значение.
    ->setQueryValue('EventId', 123)
    ->getResult();

// Для POST запросов также доступны аналогичные методы (add|set)FormData() и setFormValue().
$client
    ->userEdit()
    ->setFormData([
        'RunetId' => 1,
        'Email' => '1@mail.ru',
    ])
    ->addFormData([
        'FirstName' => 'Имя',
    ])
    ->setFormValue('LastName', 'Фамилия')
    ->getResult();

// Чтобы сконструировать запрос от начала до конца,
// можно воспользоваться методом custom().

/** @var SuccessResult $result */
$result = $client
    ->custom()
    ->setMethod('PUT')
    ->setEndpoint('/some/put/endpoint')
    ->setLanguage('en')
    ->setQueryValue('param', 'value')
    ->setFormData([
        'FormParam' => 'FormParamValue',
    ])
    ->setClass(SuccessResult::class)
    ->getResult();

// Отправка свободного Psr\Http\Message\RequestInterface осуществляется через метод request().
// Schema, host и заголовки аутентификации будут подставлены автоматически.
$request = MessageFactoryDiscovery::find()
    ->createRequest('GET', '/user/get?RunetId=1');
$resultArray = $client->request($request);

获取分页数据

库中提供的 endpoint 自动获取分页数据。

<?php

// При условии наличия 900 регистраций на мероприятии и серверном ограничении в 200 сущностей:

$endpoint = $client->eventUsers();

iterator_count($endpoint->getResult()->Users); // 900 (5 запросов),
iterator_count($endpoint->setMaxResults(340)->getResult()->Users); // 340 (2 запроса).

要获取分页数据,请使用 RunetIdClient::requestPaginated(RequestInterface $request, string $itemsKey) 方法。

参数 $itemsKey 接受可以找到分页数据数组的键。例如,对于 /event/users 方法,$itemsKey = 'Users'

在结果数组中,$itemsKey 键将包含一个提供懒加载的生成器。

抛出的异常

  1. Http\Client\Exception 会在请求执行出错时抛出。有关 HTTPLUG 异常类的更多信息,请参阅 HTTPLUG 异常类。特别是,

    • Http\Client\Common\Exception\ClientErrorException 会在响应代码为 4xx 时抛出。
    • Http\Client\Common\Exception\ServerErrorException 会在响应代码为 5xx 时抛出。
    <?php
    
    try {
        $client->userGet()
            ->setRunetId(1)
            ->getResult();
    } catch (Http\Client\Common\Exception\ServerErrorException $exception) {
        $statusCode = $exception->getResponse()->getStatusCode();
    }
  2. RunetId\Client\Exception\JsonDecodeException 会在解析 JSON 出错时抛出。

    <?php
    
    try {
        $client->userGet()
            ->setRunetId(1)
            ->getResult();
    } catch (RunetId\Client\Exception\JsonDecodeException $exception) {
        $jsonErrorMsg = $exception->getMessage();
        $jsonErrorCode = $exception->getCode();
        $invalidString = $exception->getInvalidString();
    }
  3. RunetId\Client\Exception\RunetIdException 会在 RUNET-ID API 出错时抛出。

    <?php
    
    try {
        $client->userGet()
            ->setRunetId(1)
            ->getResult();
    } catch (RunetId\Client\Exception\RunetIdException $exception) {
        $errorMessage = $exception->getMessage();
        $errorCode = $exception->getCode();
        // Метод getData() возвращает полный массив данных из ответа API.
        $data = $exception->getData();
    }
  4. RunetId\Client\Exception\ResultFactoryException 会在创建结果对象出错时抛出。

  5. RunetId\Client\Exception\UnexpectedPaginatedDataException 会在 RunetIdClient::requestPaginated() 方法中收到格式错误的响应时抛出。

关于 Result 对象的更多信息

<?php

$result = $client
    ->userGet()
    ->setRunetId(1)
    ->getResult();

// Вы можете обращаться к неразмеченным свойствам.
$result->SomeNewProperty;

// Для простоты при запросе несуществующих в исходном массиве данных
// объект не будет генерировать исключения. Вместо этого будет возвращен null.
// Это может быть полезно при обращении к свойствам,
// которые могут быть не включены в выдачу вследствие недостаточных прав.
$result->SomeLimitedAccessProperty; // null

// Чтобы проверить существование свойства в исходном массиве, используйте exists().
$hasStatus = $result->exists('Status');

// Результат является обходимым.
foreach ($result as $key => $value) {
    printf("%s: %s\n", $key, $value);
}

配置

<?php

use RunetId\Client\RunetIdClientFactory;

// Установка параметров query по умолчанию.
$factory = new RunetIdClientFactory();
$client = $factory->create(
    'key',
    'secret',
    RunetIdClientFactory::API_URI.'?Language=en&EventId=123'
);

// Использование другого базового url.
$factory = new RunetIdClientFactory();
$client = $factory->create(
    'key',
    'secret',
    'https://:8000/endpoint-prefix/?Language=en'
);

库中提供的工厂也允许使用 PHP-HTTP 项目中的任何插件。为此,请将插件数组作为第四个参数传递。例如,

为了使用 PSR-3 日志记录器记录请求,安装包 php-http/logger-plugin 并将插件连接到 RUNET-ID 客户端(请参阅 PHP-HTTP 文档中的更多信息)。

<?php

use Http\Client\Common\Plugin\LoggerPlugin;
use RunetId\Client\RunetIdClientFactory;

$loggerPlugin = new LoggerPlugin(
    // Здесь может быть любая имплементация Psr\Log\LoggerInterface.
    new Monolog\Logger('http')
);

$factory = new RunetIdClientFactory();
$client = $factory->create(
    'key',
    'secret',
    null,
    null,
    // Http\Client\Common\Plugin[]
    [$loggerPlugin]
);

可以通过第五个参数传递专门配置的 Http\Client\HttpClient 实例,该实例将由工厂装饰以与 RUNET-ID 一起使用。默认情况下,使用构造函数中提供的 HTTP 客户端或通过 Discovery 找到的客户端。

删除 Discovery 库

php-http/discovery 库允许查找已安装的 HTTP 客户端和 PSR-7 工厂实现,例如,可以将它们用作默认注入。

php-http/discovery 的依赖是软依赖。要从构建中删除此包,必须显式传递 HTTP 客户端实现和 PSR-7 工厂实现到工厂构造函数中。

例如,如果项目中使用 Guzzle 6,则工厂的初始化如下所示

<?php

$httpClient = new Http\Adapter\Guzzle6\Client();
$uriFactory = new Http\Message\UriFactory\GuzzleUriFactory();
$requestFactory = new Http\Message\MessageFactory\GuzzleMessageFactory();
$streamFactory = new Http\Message\StreamFactory\GuzzleStreamFactory();

$runetIdFactory = new RunetId\Client\RunetIdClientFactory($httpClient, $uriFactory, $requestFactory, $streamFactory);

之后,可以删除 Discovery 包 composer remove php-http/discovery

测试

vendor/bin/simple-phpunit --coverage-text