bognerf / rest-grabber
消费REST API
Requires
- php: >=7.2.0
- ext-json: *
- guzzlehttp/guzzle: ~6.0|^7.0.1
- psr/simple-cache: ^1.0
- symfony/validator: ^4.2|^5.0
Requires (Dev)
- blastcloud/guzzler: ^1.6|^2.0
- cache/cache: ^1.0
- phpunit/phpunit: ^8.0
- spatie/ray: ^1.20
- squizlabs/php_codesniffer: ^3.0
README
与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响应中的必填值。此外,您可以传递一个数组,其中包含应匹配给定键值的 约束。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"
}
]
}
如您所见,我们有多于一个潜在的值对象根,即 data 和 more-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定义全局必填值之外,您还可以为每个值对象根中的元素定义验证器。再次使用我们的REST API https://reqres.in/api/unknown,一个根级元素 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都经过检查以满足我们的约束。
自定义处理器
在某些用例中,创建自定义Handler是有意义的。例如,我们将使用Cloudflare内容分发网络的API cdnjs.com。
为了确保CDNJS的JSON响应包含我们依赖的所有关键元素,请创建自定义Handler如下(请记住,在扩展基础Handler的构造函数时,不要忘记调用 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])
]
]
]);
}
}
有趣的是,handler定义了自己的必需元素和验证规则。我们要求JSON响应包含一个 assets 元素以及一个 repository.type 元素,其值应为 git。后者是点表示法访问深层元素的绝佳例子。比较来自 CDNJS 的实际JSON。
此外,assets 下的集合或列表将构成我们的单个ValueObjects根,确保每个都包含一个 version 元素(必须存在且不为空或空白或null),以及一个 files 元素,它必须是一个包含至少两个元素的集合。
现在让我们将我们的新自定义handler投入使用
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联系,而不是使用问题跟踪器。
鸣谢
- Florian Bogner(维护者)
许可
MIT许可证(MIT)。请参阅 许可证文件 了解更多信息。