messere/php-value-mask

提取数组/对象值的子集

0.1.2 2021-02-11 11:58 UTC

This package is auto-updated.

Last update: 2024-09-11 19:57:32 UTC


README

Packagist

目的

Google在其API性能提示中,建议通过过滤响应中的未使用字段来限制所需的带宽。他们的API支持额外的URL参数fields,该参数要求API只包含响应中的特定字段。

fields参数遵循简单的语法,允许查询嵌套键、多个键或使用通配符包含所有字段(请参阅下文的语法文法部分)。

此库实现了fields参数的解析和对数组/对象的过滤。

另请参阅:基于此库的PSR-15兼容中间件:[Partial Response PSR-15 Middleware](https://github.com/Messere/partial-response-middleware)

使用示例

<?php
require_once 'vendor/autoload.php';

use messere\phpValueMask\Parser\Parser;
use messere\phpValueMask\Parser\ParserException;

$parser = new Parser();

$input = [
    'id' => 1,
    'resource' => 'book',
    'title' => 'Good Omens',
    'identifiers' => (object)[
        'isbn' => 'ISBN 83-85100-63-6​',
        'amazon' => '0060853980',  
    ],
    'authors' => [
        [
            'firstName' => 'Terry',
            'lastName' => 'Pratchett'
        ],
        [
            'firstName' => 'Neil',
            'lastName' => 'Gaiman'
        ],
    ],
    'year' => [
        'us' => 1990,
        'uk' => 1990,
        'pl' => 1992,
    ],
    'publisher' => [
        'us' => 'Workman',
        'uk' => 'Gollancz',
        'pl' => 'CIA-Books-SVARO',
    ],
];

$filter = 'title,identifiers/isbn,authors/firstName,*(us,uk),keywords';

try {
    $filteredInput = $parser->parse($filter)->filter($input);
    print_r($filteredInput);
} catch (ParserException $e) {
    echo 'Parser error: ' . $e->getMessage();
} 

让我们分析使用的过滤器元素

  • title匹配顶级元素具有键title ('Good Omens')
  • identifiers/isbn匹配顶级元素identifiers,然后包含从匹配对象中匹配的isbn元素 ('ISBN 83-85100-63-6')
  • authors/firstName查找位于键authors下的元素数组(列表),并检查所有元素,从每个元素中提取firstName。 ('Terry' 和 'Neil')
  • *(us,uk)检查所有属性并提取字段usuk。 ('1990' 和 '1990' 来自year元素,'Workman', 'Gollancz' 来自publisher)
  • keywords没有匹配任何内容,并且被静默忽略。

因此,我们期望以下输出

Array
(
    [title] => Good Omens
    [identifiers] => Array
        (
            [isbn] => ISBN 83-85100-63-6​
        )

    [authors] => Array
        (
            [0] => Array
                (
                    [firstName] => Terry
                )

            [1] => Array
                (
                    [firstName] => Neil
                )

        )

    [year] => Array
        (
            [us] => 1990
            [uk] => 1999
        )

    [publisher] => Array
        (
            [us] => Workman
            [uk] => Gollancz
        )

)

准备序列化为JSON等。

请注意,库保留了值的结构/嵌套,但不一定是值的类型 - 所有对象都转换为关联数组,对象公共属性作为键。

语法

  • a选择输入中的键a
  • a,b,c逗号分隔列表的元素:选择键abc
  • a/b/c嵌套元素:从父元素a中选择键c,该父元素本身具有父元素b
  • a(b,c)多个元素:从父元素a中选择元素bc
  • a(b,c/d)多个元素:从父元素a中选择元素b和嵌套在c中的元素d
  • a/*/c通配符:从元素a的所有子元素中选择元素c
  • *(b,c)通配符:从任何父元素中选择元素bc

等等。请参阅测试以获取更多示例以及无效过滤器的示例。

文法

由于Google没有提供其“fields”语言的详细文法,此包使用以下任意选择的规则,在作者的看来,这些规则与原始作者的意图非常相似。

用EBNF表示法

Mask         = MaskElement | MaskElement , "," , Mask ;
MaskElement  = ArrayOfMasks | NestedKeys ;
ArrayOfMasks = Key , "(" , Mask , ")" ;
NestedKeys   = Key , [ "/" , NestedKeys ] ;
Key          = Wildcard | Identifier ;
Identifier   = Letter , { Letter | Digit }
Wildcard     = "*" ;
Letter       = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" |
               "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" |
               "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" |
               "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" |
               "_";
Digit        = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0" ;

致谢

库受到以下启发:

  • Google的API性能提示
  • 类似的JavaScript库:[nemtsov/json-mask](https://github.com/nemtsov/json-mask)

许可证

MIT