bakame/http-structured-fields

PHP 中用于操作 HTTP 结构化字段的值

1.3.0 2024-01-04 23:05 UTC

This package is auto-updated.

Last update: 2024-09-11 16:56:13 UTC


README

Author Software License Build Latest Version Total Downloads Sponsor development of this project

bakame/http-structured-fields 是一个框架无关的 PHP 库,允许您根据 RFC8941 在 PHP 中解析、序列化、创建和更新 HTTP 结构化字段。

安装后,您将能够执行以下操作

use Bakame\Http\StructuredFields\DataType;
use Bakame\Http\StructuredFields\Token;

//1 - parsing an Accept Header
$fieldValue = 'text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8';
$field = DataType::List->parse($fieldValue);
$field[2]->value()->toString(); // returns 'application/xml'
$field[2]->parameter('q');      // returns (float) 0.9
$field[0]->value()->toString(); // returns 'text/html'
$field[0]->parameter('q');      // returns null

//2 - building a retrofit Cookie Header
echo DataType::List->serialize([
    [
        ['foo', 'bar'],
        [
            ['expire', new DateTimeImmutable('2023-04-14 20:32:08')],
            ['path', '/'],
            [ 'max-age', 2500],
            ['secure', true],
            ['httponly', true],
            ['samesite', Token::fromString('lax')],
        ]
    ],
]);
// returns ("foo" "bar");expire=@1681504328;path="/";max-age=2500;secure;httponly=?0;samesite=lax

系统要求

PHP >= 8.1 是必需的,但推荐使用最新稳定版本的 PHP。

安装

使用 composer

composer require bakame/http-structured-fields

文档

前言

注意

虽然此包可以解析和序列化 HTTP 值,但它不会根据任何符合性规则验证其内容。您仍然需要根据相应字段的约束执行符合性检查。内容验证不在本库的范围内,尽管您可以利用其一些功能来简化所需的验证。

解析和序列化结构化字段

基本用法

注意

新增于版本 1.2.0

要快速解析或序列化 RFC 中定义的五种(5)数据类型之一,您可以使用 DataType 枚举。除了列出可以提供给其 parse 方法的数据类型(ListInnerListParametersDictionaryItem)之外,您还可以提供一个表示字段文本表示的字符串或可转换为字符串的对象。如果成功,它将返回一个表示结构化字段的对象,否则将抛出异常。

$headerLine = 'bar;baz=42'; //the raw header line is a structured field item
$field = DataType::Item->parse($headerLine);
$field->value();          // returns Token::fromString('bar); the found token value 
$field->parameter('baz'); // returns 42; the value of the parameter or null if the parameter is not defined.

要补充行为,您可以使用其 serialize 方法将一个由成对值组成的可迭代结构转换为文本表示形式。

use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\DataType;

echo DataType::List->serialize([
    [
        'dumela lefatshe',
        [['a', false]]
    ],
    [
        ['a', 'b', Item::fromDateString('+30 minutes')],
        [['a', true]]
    ],
]);
// display "dumela lefatshe";a=?0, ("a" "b" @1703319068);a

serialize 方法是使用 create 方法将可迭代结构转换为 StructuredField 并在新生成的对象上调用其 toHttpValue 方法的快捷方式。考虑到这一点,可以重写最后一个示例。

use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\DataType;

$list = DataType::List->create([
    [
        'dumela lefatshe',
        [['a', false]]
    ],
    [
        ['a', 'b', Item::fromDateString('+30 minutes')],
        [['a', true]]
    ],
]);

echo $list->toHttpValue();
// display "dumela lefatshe";a=?0, ("a" "b" @1703319068);a

提示

虽然格式一开始可能会令人难以理解,但在阅读完其余文档后,您将理解它。在底层,DataType 枚举使用以下讨论的机制。

使用特定数据类型类

该包为每种数据类型提供了特定的类。解析是通过各自的 fromHttpValue 命名构造函数进行的。以下是一个使用 Item 类的方法示例

declare(strict_types=1);

use Bakame\Http\StructuredFields\DataType;

require 'vendor/autoload.php';

// the raw HTTP field value is given by your application
// via any given framework, package or super global.

$headerLine = 'bar;baz=42'; //the raw header line is a structured field item
$field = Item::fromHttpValue($headerLine);
$field->value();          // returns Token::fromString('bar); the found token value 
$field->parameter('baz'); // returns 42; the value of the parameter or null if the parameter is not defined.

提示

DataType::parse 方法使用每个特定类的 fromHttpValue 命名构造函数来生成结构化字段的 PHP 表示形式。

fromHttpValue 方法返回一个实现了 StructuredField 接口的实例。该接口提供了一个 toHttpValue 方法,该方法将其序列化为符合 RFC 的标准 HTTP 字段字符串值。为了便于集成,已实现 __toString 方法作为 toHttpValue 方法的别名。

$field = Item::fromHttpValue('bar;    baz=42;     secure=?1');
echo $field->toHttpValue(); // return 'bar;baz=42;secure'
// on serialization the field has been normalized

// the HTTP response is build by your application
// via any given framework, package or PHP native function.

header('foo: '. $field->toHttpValue());
//or
header('foo: '. $field);

提示

这是由 DataType::serialize 方法使用的机制。一旦创建了结构化字段,该方法就会调用其 toHttpValue 方法。

RFC 中定义的所有五种(5)结构化数据类型都在 Bakame\Http\StructuredFields 命名空间中提供。它们都实现了 StructuredField 接口并公开了 fromHttpValue 命名构造函数。

  • 项目
  • 参数
  • 字典
  • OuterList(在 RFC 中命名为 List,但在包中重命名为 list,因为在 PHP 中 list 是保留字。)
  • 内部列表

访问结构化字段值

RFC 值类型

根据RFC,项目值可以有不同的类型,可以通过以下方式在PHP中转换:

  • 尽可能使用原生类型或类;
  • 在包命名空间中定义的特定类来表示非原生类型;

下表总结了项目值类型。

注意

《日期》和《显示字符串》类型目前还不是任何接受的RFC的一部分。但它们已经被添加到超补丁RFC提案中的新类型中。

更多信息请参见https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-sfbis

枚举《类型》列出所有可用类型,并可以使用《Type::fromVariable》静态方法确定与PHP结构对应的RFC类型。如果结构不被识别,则该方法将抛出异常。作为替代,可以使用《Type::tryFromVariable》,它将在未识别的类型上返回《null》。成功时,这两种方法都返回相应的枚举《Type》。

use Bakame\Http\StructuredFields\Type;

echo Type::fromVariable(42)->value;  // returns 'integer'
echo Type::fromVariable(42.0)->name; // returns 'Decimal'
echo Type::fromVariable(new SplTempFileObject()); // throws InvalidArgument
echo Type::tryFromVariable(new SplTempFileObject()); // returns null

为了简化验证,公开了《Type::equals》方法来检查《Item》是否具有预期的类型。它也可以用于比较类型。

use Bakame\Http\StructuredFields\DataType;
use Bakame\Http\StructuredFields\Type;

$field = DataType::Item->parse('"foo"');
Type::Date->equals($field);          // returns false
Type::String->equals($field);        // returns true;
Type::Boolean->equals(Type::String); // returns false

RFC定义了三种(3)不能由PHP默认类型系统表示的特定数据类型,对于这些类型,我们定义了三个类《Token》、《ByteSequence》和《DisplayString》来帮助它们的表示。

use Bakame\Http\StructuredFields\ByteSequence;
use Bakame\Http\StructuredFields\DisplayString;
use Bakame\Http\StructuredFields\Token;

Token::fromString(string|Stringable $value): Token
ByteSequence::fromDecoded(string|Stringable $value): ByteSequence;
ByteSequence::fromEncoded(string|Stringable $value): ByteSequence;
DisplayString::fromDecoded(string|Stringable $value): DisplayString;
DisplayString::fromEncoded(string|Stringable $value): DisplayString;

所有类都是最终的和不可变的;它们的值一旦实例化后就不能修改。要访问它们的值,它们公开以下API:

use Bakame\Http\StructuredFields\Token;
use Bakame\Http\StructuredFields\ByteSequence;
use Bakame\Http\StructuredFields\DisplayString;

$token = Token::fromString('application/text+xml');
echo $token->toString(); // returns 'application/text+xml'

$displayString = DisplayString::fromDecoded('füü');
$displayString->decoded(); // returns 'füü'
$displayString->encoded(); // returns 'f%c3%bc%c3%bc'

$byte = ByteSequence::fromDecoded('Hello world!');
$byte->decoded(); // returns 'Hello world!'
$byte->encoded(); // returns 'SGVsbG8gd29ybGQh'

$token->equals($byte); // will return false;
$displayString->equals($byte); // will return false;
$byte->equals(ByteSequence::fromEncoded('SGVsbG8gd29ybGQh')); // will return true

$token->type(); // returns Type::Token enum
$byte->type();  // returns Type::ByteSequence
$displayString->type(); // returns Type::DisplayString

警告

这些类不公开《Stringable》接口,以帮助将它们与字符串或可字符串化对象区分开来。

项目

定义的类型都附加到《Item》对象上,可以使用以下方法访问它们的值和类型:

use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Type;

$item = Item::fromHttpValue('@1234567890');
$item->type();  // return Type::Date;
$item->value()  // return the equivalent to DateTimeImmutable('@1234567890');

容器

所有容器对象都实现了PHP的《IteratorAggregate》、《Countable》和《ArrayAccess》接口。它们的成员可以使用以下共享方法访问:

$container->keys(): array<string|int>;
$container->has(string|int ...$offsets): bool;
$container->get(string|int $offset): StrucuredField;
$container->hasMembers(): bool;
$container->hasNoMembers(): bool;

重要

如果不存在给定《$offset》的成员,则《get》方法将抛出《InvalidOffset》异常。

为了避免无效状态,如果尝试在任何容器对象上使用,则《ArrayAccess》修改方法将抛出《ForbiddenOperation》异常。

use Bakame\Http\StructuredFields\Parameters;

$value = Parameters::fromHttpValue(';a=foobar');
$value->has('b');     // return false
$value['a']->value(); // return 'foobar'
$value['b'];          // triggers a InvalidOffset exception, the index does not exist
$value['a'] = 23      // triggers a ForbiddenOperation exception
unset($value['a']);   // triggers a ForbiddenOperation exception

《Dictionary》和《Parameters》类还允许将其成员作为对来访问。

$container->hasPair(int ...$offsets): bool;
$container->pair(int $offset): array{0:string, 1:StructuredField};
$container->toPairs(): iterable<array{0:string, 1:StructuredField}>;

重要

如果不存在给定《$offset》的成员,则《pair》方法将抛出《InvalidOffset》异常。

访问参数值

使用以下方法访问附加到《InnerList》或《Item》实例的关联《Parameters》实例:

use Bakame\Http\StructuredFields\InnerList;
use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Parameters;

$field->parameter(string $key): ByteSequence|Token|DisplayString|DateTimeImmutable|Stringable|string|int|float|bool|null;
$field->parameters(): Parameters;
$field->parameterByIndex(int $index): array{0:string, 1:ByteSequence|Token|DisplayString|DateTimeImmutable|Stringable|string|int|float|boo}
InnerList::toPair(): array{0:list<Item>, 1:Parameters}>};
Item::toPair(): array{0:ByteSequence|Token|DisplayString|DateTimeImmutable|Stringable|string|int|float|bool, 1:Parameters}>};

注意

  • 如果找不到给定键的值,则《parameter》方法将返回《null》。
  • 《parameterByIndex》方法在《版本1.1.0》中添加,如果未找到给定索引的参数,则返回空数组。

构建和更新结构化字段值

每个值对象都可以用作构建器来创建HTTP字段值。因为我们使用不可变值对象,所以对值对象的任何更改都将返回一个新的实例,其中包含应用了更改的实例,而原始实例保持不变。

项目值

《Item》值对象公开以下命名构造函数来实例化裸项(即:没有附加参数的项)。

use Bakame\Http\StructuredFields\ByteSequence;
use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Token;

Item:new(DateTimeInterface|ByteSequence|Token|DisplayString|string|int|array|float|bool $value): self
Item::fromDecodedByteSequence(Stringable|string $value): self;
Item::fromEncodedDisplayString(Stringable|string $value): self;
Item::fromDecodedDisplayString(Stringable|string $value): self;
Item::fromEncodedByteSequence(Stringable|string $value): self;
Item::fromToken(Stringable|string $value): self;
Item::fromString(Stringable|string $value): self;
Item::fromDate(DateTimeInterface $datetime): self;
Item::fromDateFormat(string $format, string $datetime): self;
Item::fromDateString(string $datetime, DateTimeZone|string|null $timezone = null): self;
Item::fromTimestamp(int $value): self;
Item::fromDecimal(int|float $value): self;
Item::fromInteger(int|float $value): self;
Item::true(): self;
Item::false(): self;

要更新《Item》实例值,请使用《withValue》方法。

use Bakame\Http\StructuredFields\Item;

Item::withValue(DateTimeInterface|ByteSequence|Token|DisplayString|string|int|float|bool $value): static

有序映射

《Dictionary》和《Parameters》是有序映射实例。它们可以使用以下关联可迭代结构使用其键构建:

use Bakame\Http\StructuredFields\Dictionary;

$value = Dictionary::fromAssociative([
    'b' => Item::false(),
    'a' => Item::fromToken('bar'),
    'c' => new DateTimeImmutable('2022-12-23 13:00:23'),
]);

echo $value->toHttpValue(); //"b=?0, a=bar, c=@1671800423"
echo $value;                //"b=?0, a=bar, c=@1671800423"

或使用其索引使用RFC中定义的对(元组)的可迭代结构。

use Bakame\Http\StructuredFields\Parameters;
use Bakame\Http\StructuredFields\Item;

$value = Parameters::fromPairs(new ArrayIterator([
    ['b', Item::false()],
    ['a', Item::fromToken('bar')],
    ['c', new DateTime('2022-12-23 13:00:23')]
]));

echo $value->toHttpValue(); //;b=?0;a=bar;c=@1671800423
echo $value;                //;b=?0;a=bar;c=@1671800423

如果偏好使用构建器模式,可以通过以下步骤达到相同的结果:

  • 首先,使用名为构造函数的 new 创建一个 ParametersDictionary 实例,该构造函数返回一个没有任何成员的新实例。
  • 然后,使用以下任何一种修改方法来填充它。
$map->add(string $key, $value): static;
$map->append(string $key, $value): static;
$map->prepend(string $key, $value): static;
$map->mergeAssociative(...$others): static;
$map->mergePairs(...$others): static;
$map->remove(string|int ...$key): static;

如下所示:

use Bakame\Http\StructuredFields\Dictionary;
use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Token;

$value = Dictionary::new()
    ->add('a', InnerList::new(
        Item::fromToken('bar'),
        Item::fromString('42'),
        Item::fromInteger(42),
        Item::fromDecimal(42)
     ))
    ->prepend('b', Item::false())
    ->append('c', Item::fromDateString('2022-12-23 13:00:23'))
;

echo $value->toHttpValue(); //b=?0, a=(bar "42" 42 42.0), c=@1671800423
echo $value;                //b=?0, a=(bar "42" 42 42.0), c=@1671800423

从版本 1.1.0 开始,也可以使用 RFC 中描述的索引和配对来构建 DictionaryParameters 实例。

$pair 参数是一个元组(即:具有两个成员的列表),其中

  • 第一个数组成员是参数 $key
  • 第二个数组成员是参数 $value
// since version 1.1
$map->unshift(array ...$pairs): static;
$map->push(array ...$pairs): static;
$map->insert(int $key, array ...$pairs): static;
$map->replace(int $key, array $pair): static;
$map->removeByKeys(string ...$keys): static;
$map->removeByIndices(int ...$indices): static;

我们可以重写前面的示例

use Bakame\Http\StructuredFields\Dictionary;
use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Token;

$value = Dictionary::new()
    ->push(
        ['a', InnerList::new(
            Item::fromToken('bar'),
            Item::fromString('42'),
            Item::fromInteger(42),
            Item::fromDecimal(42)
         )],
         ['c', Item::true()]
     )
    ->unshift(['b', Item::false()])
    ->replace(2, ['c', Item::fromDateString('2022-12-23 13:00:23')])
;

echo $value->toHttpValue(); //b=?0, a=(bar "42" 42 42.0), c=@1671800423
echo $value;                //b=?0, a=(bar "42" 42 42.0), c=@1671800423

注意

在重复的 keys 上,根据 RFC 逻辑合并配对值。

remove 始终接受字符串或整数作为输入。从版本 1.1 开始,如果方法提供了索引,则该方法将固定删除相应的配对。

<?php

use Bakame\Http\StructuredFields\Dictionary;

$field = Dictionary::fromHttpValue('b=?0, a=(bar "42" 42 42.0), c=@1671800423');
- echo $field->remove('b', 2)->toHttpValue(); // returns a=(bar "42" 42 42.0), c=@1671800423
+ echo $field->remove('b', 2)->toHttpValue(); // returns a=(bar "42" 42 42.0)

如果需要更严格的方法,请使用以下新方法 removeByIndices 和/或 removeByKeys

use Bakame\Http\StructuredFields\Parameters;

$field = Parameters::fromHttpValue(';expire=@1681504328;path="/";max-age=2500;secure;httponly=?0;samesite=lax');
echo $field->removeByIndices(4, 2, 0)->toHttpValue();                      // returns ;path="/";secure;samesite=lax
echo $field->removeByKeys('expire', 'httponly', 'max-age')->toHttpValue(); // returns ;path="/";secure;samesite=lax

自动转换

对于所有容器,为了简化实例化,以下自动转换应用于每个修改方法的成员参数。

如果提交的类型是

  • 实现对象的结构化字段,则将按原样传递
  • 可迭代结构,它将被转换为使用 InnerList::new 创建的 InnerList 实例
  • 否则,它将被转换为使用 Item::new 命名构造函数的 Item

如果无法进行转换,将抛出 InvalidArgument 异常。

这意味着以下两种结构都构建了相同的对象

use Bakame\Http\StructuredFields\Dictionary;
use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Token;

echo Dictionary::new()
    ->add('a', InnerList::new(
        Item::fromToken('bar'),
        Item::fromString('42'),
        Item::fromInteger(42),
        Item::fromDecimal(42)
     ))
    ->prepend('b', Item::false())
    ->append('c', Item::fromDateString('2022-12-23 13:00:23'))
    ->toHttpValue()
;

echo Dictionary::new()
    ->add('a', [Token::fromString('bar'), '42', 42, 42.0])
    ->prepend('b', false)
    ->append('c', new DateTimeImmutable('2022-12-23 13:00:23'))
    ->toHttpValue()
;

 // both will return 'b=?0, a=(bar "42" 42 42.0), c=@1671800423

当然,也可以混合使用这两种表示法。

列表

要创建 OuterListInnerList 实例,可以使用接受单个可变参数 $membersnew 命名构造函数。

use Bakame\Http\StructuredFields\InnerList;
use Bakame\Http\StructuredFields\ByteSequence;

$list = InnerList::new(
    ByteSequence::fromDecoded('Hello World'),
    42.0,
    42
);

echo $list->toHttpValue(); //'(:SGVsbG8gV29ybGQ=: 42.0 42)'
echo $list;                //'(:SGVsbG8gV29ybGQ=: 42.0 42)'

再次强调,可以通过组合 new 命名构造函数和以下修改方法之一来使用构建器模式。

$list->unshift(...$members): static;
$list->push(...$members): static;
$list->insert(int $key, ...$members): static;
$list->replace(int $key, $member): static;
$list->remove(int ...$key): static;

如下所示

use Bakame\Http\StructuredFields\ByteSequence;
use Bakame\Http\StructuredFields\InnerList;

$list = InnerList::new()
    ->unshift('42')
    ->push(42)
    ->insert(1, 42.0)
    ->replace(0, ByteSequence::fromDecoded('Hello World'));

echo $list->toHttpValue(); //'(:SGVsbG8gV29ybGQ=: 42.0 42)'
echo $list;                //'(:SGVsbG8gV29ybGQ=: 42.0 42)'

注意

新增于版本 1.2.0

也可以根据配对的可迭代结构创建一个 OuterList

use Bakame\Http\StructuredFields\OuterList;

$list = OuterList::fromPairs([
    [
        ['foo', 'bar'],
        [
            ['expire', new DateTime('2024-01-01 12:33:45')],
            ['path', '/'],
            [ 'max-age', 2500],
            ['secure', true],
            ['httponly', true],
            ['samesite', Token::fromString('lax')],
        ]
    ],
    [
        'coucoulesamis', 
        [['a', false]],
    ]
]);

配对定义与使用各自的 fromPair 方法创建 InnerListItem 相同。

添加和更新参数

为了简化处理附加有 Parameters 对象的实例的工作,添加了以下方法

use Bakame\Http\StructuredFields\ByteSequence;
use Bakame\Http\StructuredFields\InnerList;
use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Token;

//@type SfItemInput ByteSequence|Token|DateTimeInterface|string|int|float|bool

Item::fromAssociative(SfItemInput $value, Parameters|iterable<string, SfItemInput> $parameters): self;
Item::fromPair(array{0:SfItemInput, 1:Parameters|iterable<array{0:string, 1:SfItemInput}>} $pair): self;

InnerList::fromAssociative(iterable<SfItemInput> $value, Parameters|iterable<string, SfItemInput> $parameters): self;
InnerList::fromPair(array{0:iterable<SfItemInput>, Parameters|iterable<array{0:string, 1:SfItemInput}>} $pair): self;

以下示例说明了如何使用这些方法

use Bakame\Http\StructuredFields\Dictionary;
use Bakame\Http\StructuredFields\Item;

echo Item::fromAssociative(
        Token::fromString('bar'),
        ['baz' => 42]
    )->toHttpValue(), PHP_EOL;

echo Item::fromPair([
        Token::fromString('bar'),
        [['baz', 42]],
    ])->toHttpValue(), PHP_EOL;

//both methods return `bar;baz=42`

这两个对象都提供了额外的修改方法来帮助处理参数。可以使用以下方法附加和更新关联的 Parameters 实例。

$field->addParameter(string $key, mixed $value): static;
$field->appendParameter(string $key, mixed $value): static;
$field->prependParameter(string $key, mixed $value): static;
$field->withoutParameters(string ...$keys): static; // this method is deprecated as of version 1.1 use withoutParametersByKeys instead
$field->withoutAnyParameter(): static;
$field->withParameters(Parameters $parameters): static;

从版本 1.1 开始,也可以使用每个成员的索引来执行附加修改。

$field->pushParameters(array ...$pairs): static
$field->unshiftParameters(array ...$pairs): static
$field->insertParameters(int $index, array ...$pairs): static
$field->replaceParameter(int $index, array $pair): static
$field->withoutParametersByKeys(string ...$keys): static
$field->withoutParametersByIndices(int ...$indices): static

$pair 参数是一个元组(即:具有两个成员的列表),其中

  • 第一个数组成员是参数 $key
  • 第二个数组成员是参数 $value

警告

返回值将是父类而不是 Parameters 实例

use Bakame\Http\StructuredFields\InnerList;
use Bakame\Http\StructuredFields\Item;

echo InnerList::new('foo', 'bar')
    ->addParameter('expire', Item::fromDateString('+30 minutes'))
    ->addParameter('path', '/')
    ->addParameter('max-age', 2500)
    ->toHttpValue();

echo InnerList::new('foo', 'bar')
    ->pushParameter(
        ['expire', Item::fromDateString('+30 minutes')],
        ['path', '/'],
        ['max-age', 2500],
    )
    ->toHttpValue();

// both flow return the InnerList HTTP value 
// ("foo" "bar");expire=@1681538756;path="/";max-age=2500

高级解析用法

从版本 1.1 开始,内部解析器已公开,以便

  • 解析和对象构建之间的更清晰的解耦
  • 不同的解析器实现
  • 改进测试中的包使用。

每个 fromHttpValue 方法签名都已更新,以接受第二个可选参数,该参数表示用于解析 HTTP 字符串表示值所需的解析器接口。

默认情况下,如果没有提供解析器,则包将默认使用包的 Parser 类,

Item::fromHttpValue(Stringable|string $httpValue, ItemParser $parser = new Parser()): Item;
InnerList::fromHttpValue(Stringable|string $httpValue, InnerListParser $parser = new Parser()): InnerList;
Dictionary::fromHttpValue(Stringable|string $httpValue, DictionaryParser $parser = new Parser()): Dictionary;
OuterList::fromHttpValue(Stringable|string $httpValue, ListParser $parser = new Parser()): OuterList;
Parameters::fromHttpValue(Stringable|string $httpValue, ParametersParser $parser = new Parser()): Parameters;

Parser 类公开以下方法,每个方法都属于不同的契约或接口。

Parser::parseValue(Stringable|string $httpValue): ByteSequence|Token|DateTimeImmutable|string|int|float|bool;
Parser::parseItem(Stringable|string $httpValue): array;
Parser::parseParameters(Stringable|string $httpValue): array;
Parser::parseInnerList(Stringable|string $httpValue): array;
Parser::parseList(Stringable|string $httpValue): array;
Parser::parseDictionary(Stringable|string $httpValue): array;

一旦实例化,调用上述列出的方法就很简单了

use Bakame\Http\StructuredFields\Parser;

$parser = new Parser();
$parser->parseValue('text/csv'); //returns Token::fromString('text/csv')
$parser->parseItem('@1234567890;file=24'); 
//returns an array
//  [
//    new DateTimeImmutable('@1234567890'),
//    ['file' => 24],
//  ]

注意

虽然提供的默认Parser类实现了所有这些方法,但您可以根据需要只实现您需要的那些方法。

贡献

欢迎贡献,贡献将得到充分认可。请参阅CONTRIBUTING行为准则以获取详细信息。

测试

要运行测试,请在项目文件夹中运行以下命令。

composer test

安全性

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

鸣谢

归属

该包的内部解析器深受GapplePHP的结构化字段值上的先前工作的启发。

许可证

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