bognerf/rest-grabber 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

bognerf/rest-grabber

Composer 安装命令:

composer require bognerf/rest-grabber

包简介

Consume REST APIs

README 文档

README

Coverage Latest Stable Version Total Downloads License

Work with REST APIs and assure the presence and validity of certain elements within the JSON response.

Table of Contents

Via Composer

$ composer require bognerf/rest-grabber

Usage

Basic usage without any validation or generation of derived objects (ValueObjects) is quite straightforward:

use Bognerf\RestGrabber\Grabber;
use Bognerf\RestGrabber\Url;

$url = new Url('https://reqres.in/api/unknown/2');
$grabber = new Grabber($url);
$contents = $grabber->get()->grab()->data();

You'll get an array according to the JSON provided by the response of https://reqres.in/api/unknown/2;

Global validation Rules

You can pass an array with dot notated keys to define obligatory values in the JSON response. Additionally, you can pass an array of constraints the value of the given key should match. RestGrabber relies on Symfony's Constraint library.

use Bognerf\RestGrabber\Grabber;
use Bognerf\RestGrabber\Url;

$url = new Url('https://reqres.in/api/users/2');
$grabber = new Grabber($url);
$grabber->getHandler()->setObligatoryFields([
    'data' => [
        new \Symfony\Component\Validator\Constraints\Count(['min'=>5])
    ],
    'data.email' => [
      new \Symfony\Component\Validator\Constraints\Email()
    ]
]);
$grabber->get()->grab();

The example above would query https://reqres.in/api/users/2 and make sure that the root level element data contains at least five sub-elements. Further, as denoted by data.email an element email must be present under data, which syntactically must conform to an email address.

ValueObjects

RestGrabber generates ValueObjects from certain sub-elements in our JSON (possibly even from the root element, if you so wish). For this to work, we must pass a Handler to our RestGrabber instance. By default, the library provides a generic Handler Bognerf\RestGrabber\Handlers\PlainJson. All handlers must extend the abstract class Bognerf\RestGrabber\Handler.

How to use them

Consider the following JSON example 1 (taken from https://reqres.in/api/unknown/):

{
  "page": 1,
  "per_page": 3,
  "total": 12,
  "total_pages": 4,
  "data": [
    {
      "id": 1,
      "name": "cerulean",
      "year": 2000,
      "color": "#98B2D1",
      "pantone_value": "15-4020"
    },
    {
      "id": 2,
      "name": "fuchsia rose",
      "year": 2001,
      "color": "#C74375",
      "pantone_value": "17-2031"
    },
    {
      "id": 3,
      "name": "true red",
      "year": 2002,
      "color": "#BF1932",
      "pantone_value": "19-1664"
    }
  ]
}

There are three objects listed under data. With RestGrabber you can define data as a ValueObject root element (deeper nesting is also possible using dot notation, e.g. data.sub-element), to automatically parse them and create a ValueObject from each of the three entries. Let's have a look:

use Bognerf\RestGrabber\Grabber;
use Bognerf\RestGrabber\Url;

$url = new Url('https://reqres.in/api/unknown');
$grabber = new Grabber($url);

$grabber->getHandler()->addValueObjectsRoot([
    'data' => []
]);
$grabber->get()->grab();
$valueObjects = $grabber->valueObjects('data');

We rely on the built-in Handler PlainJson. $valueObjects is now an array of three ValueObjects, which could be used like so:

foreach ($valueObjects as $vo) {
    echo $vo->getName() . PHP_EOL;
}

getName() is a magic getter function. You could retrieve any element of a ValueObject by get plus uppercased first letter of the element.

Additionally, usual magic getters are also available:

foreach ($valueObjects as $vo) {
    echo $vo->color . PHP_EOL;
}
JSON example 2

You aren't limited to only a single ValueObject root, there can be more. Consider our now slightly changed JSON:

{
  "page": 1,
  "per_page": 3,
  "total": 12,
  "total_pages": 4,
  "data": [
    {
      "id": 1,
      "name": "cerulean",
      "year": 2000,
      "color": "#98B2D1",
      "pantone_value": "15-4020"
    },
    {
      "id": 2,
      "name": "fuchsia rose",
      "year": 2001,
      "color": "#C74375",
      "pantone_value": "17-2031"
    },
    {
      "id": 3,
      "name": "true red",
      "year": 2002,
      "color": "#BF1932",
      "pantone_value": "19-1664"
    }
  ],
  "more-data": [
    {
    "id": 1,
    "name": "Florian"
    },
    {
    "id": 2,
    "name": "Katharina"
    }
  ]
}

As you can see, we have more than one potential ValueObject roots, namely data and more-data. Simply add more-data as a second ValueObject root:

use Bognerf\RestGrabber\Grabber;
use Bognerf\RestGrabber\Url;

$url = new Url('https://reqres.in/api/unknown');
$grabber = new Grabber($url);

$grabber->getHandler()->addValueObjectsRoot([
    'data' => []
]);

$grabber->getHandler()->addValueObjectsRoot([
    'more-data' => []
]);

$grabber->get()->grab();
$valueObjectsData = $grabber->getHandler()->valueObjects('data');
$valueObjectsMoreData = $grabber->getHandler()->valueObjects('more-data');

ValueObjects validation rules

Beyond defining obligatory values on a global scale for the whole JSON, you can also define validators for elements in each ValueObject root. Working again with our REST API at https://reqres.in/api/unknown , a root level element data having several objects could be defined as the ValueObject's root level. Remember, the root of ValueObjects is also made in dot notation. Let's see how to achieve this:

use Bognerf\RestGrabber\Grabber;
use Bognerf\RestGrabber\Url;

$url = new Url('https://reqres.in/api/unknown');
$grabber = new Grabber($url);

$grabber->getHandler()->addValueObjectsRoot([
    'data' => [
        'id' => [],
        'name' => [
            new \Symfony\Component\Validator\Constraints\Length(['min' => 3, 'max' => 128])
        ],
        'pantone_value' => [
            new \Symfony\Component\Validator\Constraints\Regex([
                'pattern' => '/^([0-9]){2}\-([0-9]){4}$/'
            ])
        ]
    ]
]);
$grabber->get()->grab();
$valueObjects = $grabber->valueObjects('data');

The example above would query https://reqres.in/api/unknown and validate that the root level element data exists and contains at least two elements. The root for our ValueObjects will also be set to data. Within data, each element must have an element id without further constraints, and an element name which should be at least three and at most 100 characters long. Finally, $grabber->valueObjects('data) will return an array of ValueObjects, each of which was checked to fulfill our constraints.

Custom handlers

For certain use cases it'll make sense to create a custom Handler. As an example, we'll use the API of Cloudflare's content delivery network cdnjs.com.

To ensure CDNJS's JSON response contains all critical elements we rely on, create your custom Handler like so (please don't forget to call parent::__construct() when extending the base Handler's constructor:

class CdnjsHandler extends \Bognerf\RestGrabber\Handler
{
    public function __construct()
    {
        parent::__construct();
        $this->obligatoryFields = [
            'assets' => [],
            'repository.type' => [
                new \Symfony\Component\Validator\Constraints\EqualTo(['value' => 'git']),
            ],
        ];

        $this->addValueObjectsRoot([
            'assets' => [
                'version' => [
                    new \Symfony\Component\Validator\Constraints\NotBlank(),
                ],
                'files' => [
                    new \Symfony\Component\Validator\Constraints\Count(['min' => 2])
                ]
            ]
        ]);
    }

}

The charming part is that the handler defines its own obligatory elements and validation rules. We're requiring the JSON response to contain an element assets as well as an element repository.type, which should have the value git. The latter being a great example for dot notated deeper level elements. Compare the actual JSON from CDNJS.

Furthermore, the collection or list under assets will consitute our single ValueObjects root, assuring that each and every one of it contains an element version (which must be present and not blank or empty or null) and an element files, which must be a collection with at least two elements.

Now let's put our new custom handler to service:

use Bognerf\RestGrabber\Grabber;
use Bognerf\RestGrabber\Url;

$url = new Url('https://api.cdnjs.com/libraries/axios');
$grabber = new Grabber($url);

$grabber->setHandler(new CdnjsHandler());

$grabber->get()->grab();
$valueObjects = $grabber->valueObjects('assets');

dump($valueObjects);

Working with Cache

RestGrabber can take a PSR-16 compatible CacheInterface via RestGrabber::setCache(). We'll use ZendCache, which is why we have to require some dependencies:

$ composer require zendframework/zend-cache
$ composer require zendframework/zend-serializer

But remember, you could use any PSR-16 compatible CacheInterface. It does not have to be Zend's.

$storage = StorageFactory::factory([
    'adapter' => [
        'name' => 'filesystem',
        'options' => [
            'cache_dir' => '/tmp/rest-grabber',
        ],
    ],
    'plugins' => [
        'serializer',
    ],
]);

$cache = new SimpleCacheDecorator($storage);

$url = new Url('https://api.cdnjs.com/libraries/axios');
$grabber = new Grabber($url);
$grabber->setCache($cache);
echo ($grabber->isCached() ? "Hit":"Missed");
$grabber->setHandler(new \RestGrabberTestbed\Handlers\CdnjsHandler());

$grabber->get()->grab();
$valueObjects = $grabber->valueObjects('assets');
echo ($grabber->isCached() ? "Hit":"Missed");

Testing

$ composer test

Security

If you discover any security related issues, please email fb@florianbogner.de instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

bognerf/rest-grabber 适用场景与选型建议

bognerf/rest-grabber 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 310 次下载、GitHub Stars 达 0, 最近一次更新时间为 2019 年 05 月 21 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「json」 「api」 「restful」 「bognerf」 「rest-grabber」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 bognerf/rest-grabber 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 bognerf/rest-grabber 我们能提供哪些服务?
定制开发 / 二次开发

基于 bognerf/rest-grabber 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 310
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 4
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-05-21