bognerf/rest-grabber-legacy

消耗 REST API(兼容 PHP 7.0 的回滚版本)

v0.9.0 2019-06-03 12:39 UTC

This package is auto-updated.

Last update: 2024-09-29 05:42:19 UTC


README

这是一个为与 PHP7.0 兼容而回滚的版本。在几乎所有情况下,您都应该使用 bognerf/rest-grabber

与 REST API 一起使用并确保 JSON 响应中存在并有效某些元素。

目录

通过 Composer

$ composer require bognerf/rest-grabber

用法

无验证或派生对象(值对象)生成的基本用法相当简单

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();

您将根据 https://reqres.in/api/unknown/2 的响应提供的 JSON 获得一个数组;

全局验证规则

您可以通过点分隔的键的数组来定义 JSON 响应中的必填值。此外,您还可以传递一个 约束 数组,给定键的值应与之匹配。RestGrabber 依赖于 Symfony 的约束库

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();

上面的例子将查询 https://reqres.in/api/users/2 并确保根级元素 data 至少包含五个子元素。此外,如 data.email 所示,必须在 data 下存在一个 email 元素,其语法必须符合电子邮件地址。

值对象

RestGrabber 从我们 JSON 的某些子元素(甚至可能是根元素,如果您愿意的话)生成值对象。为了使其工作,我们必须将一个 Handler 传递给我们的 RestGrabber 实例。默认情况下,库提供了一个通用的处理器 Bognerf\RestGrabber\Handlers\PlainJson。所有处理器都必须扩展抽象类 Bognerf\RestGrabber\Handler

如何使用它们

考虑以下 JSON 示例 1(从 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"
    }
  ]
}

data 下有三个对象。使用 RestGrabber,您可以定义 data 作为值对象的根元素(也可以使用点表示法进行更深层次的嵌套,例如 data.sub-element),自动解析它们并从每个条目创建一个值对象。让我们看看

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');

我们依赖于内置的处理器 PlainJson。现在 $valueObjects 是一个包含三个值对象的数组,可以使用以下方式使用

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

getName() 是一个魔法获取器函数。您可以通过 get 加上 元素的第一个字母大写 来检索值对象的任何元素。

此外,还有常见的魔法获取器

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

您不仅限于只有一个值对象根,可以有多个。考虑我们稍作修改的 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"
    }
  ]
}

如您所见,我们有多于一个潜在的值对象根,即 datamore-data。只需将 more-data 添加为第二个值对象根即可

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');

值对象验证规则

除了为整个 JSON 在全局范围内定义必填值之外,您还可以为每个值对象根中的元素定义验证器。再次使用我们位于 https://reqres.in/api/unknown 的 REST API,根级元素 data 包含多个对象,可以将其定义为值对象的根级。记住,值对象的根也使用点表示法。让我们看看如何实现这一点

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');

上面的示例会查询 https://reqres.in/api/unknown 并验证根级别元素 data 存在且包含至少两个元素。我们ValueObjects的根也将设置为 data。在data中,每个元素必须有一个没有其他约束的 id 元素,以及一个 name 元素,其长度应至少为三个字符,最多为100个字符。最后,$grabber->valueObjects('data') 将返回一个ValueObjects数组,每个ValueObjects都经过检查以符合我们的约束。

自定义处理器

对于某些用例,创建自定义处理器是有意义的。例如,我们将使用Cloudflare内容分发网络的API cdnjs.com

为了确保CDNJS的JSON响应包含我们依赖的所有关键元素,创建您的自定义处理器如下(请记住,在扩展基础处理器的构造函数时,不要忘记调用 parent::__construct())。

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])
                ]
            ]
        ]);
    }

}

有趣的部分是处理器定义了自己的必需元素和验证规则。我们要求JSON响应包含一个元素 assets 以及一个元素 repository.type,其值应该是 git。后者的存在是一个很好的点表示深层元素示例。比较来自 CDNJS 的实际JSON。

此外,位于 assets 下的集合或列表将构成我们的单个ValueObjects根,确保每个元素都包含一个 version 元素(必须存在且不为空、空或null)和一个 files 元素,它必须是一个包含至少两个元素的集合。

现在让我们使用我们新的自定义处理器。

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);

与缓存一起工作

RestGrabber可以通过 RestGrabber::setCache() 接受一个 PSR-16 兼容的CacheInterface。我们将使用ZendCache,因此我们必须引入一些依赖项。

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

但请记住,您可以使用任何PSR-16兼容的CacheInterface。它不一定是Zend的。

$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");

测试

$ composer test

安全

如果您发现任何安全相关的问题,请通过电子邮件fb@florianbogner.de联系,而不是使用问题跟踪器。

致谢

许可

MIT许可(MIT)。有关更多信息,请参阅 许可文件