cerbero/transformer

转换、操作、类型转换和映射对象和数组。

2.4.0 2021-01-14 07:31 UTC

This package is auto-updated.

Last update: 2024-09-14 16:24:14 UTC


README

Author PHP Version Build Status Coverage Status Quality Score Latest Version Software License PSR-12 Total Downloads

SensioLabsInsight

一个无框架的包,通过操作、类型转换和映射属性和键来转换数组、对象、数组的数组或对象的数组。

安装

通过Composer

$ composer require cerbero/transformer

使用方法

可以通过扩展AbstractTransformer类来创建转换器

use Cerbero\Transformer\AbstractTransformer;

class MyTransformer extends AbstractTransformer
{
    protected function getStructure()
    {
        // the array structure you want to obtain
    }
}

getStructure()方法允许您定义您想要如何转换数据。例如,假设这个数组

[
    'some' => [
        'nested' => [
            'key' => 'hello',
        ],
    ],
    'color'           => 'blue',
    'adminPermission' => '1',
    'status'          => 'pending',
    'date'            => '2015-01-01T00:00:00+00:00',
    'number'          => '22',
    'cents'           => '$0.0500',
    'unneeded'        => true,
    'json'            => '{"foo":"bar"}',
]

需要被转换成

[
    'key' => 'hello',
    'favorites' => [
        'color'  => 'blue',
        'number' => 22,
    ],
    'is_admin'  => true,
    'status'    => 2,
    'important' => [
        'date'  => '2015-01-01',
    ],
    'cents'     => 0.05,
    'json'      => ['foo' => 'bar'],
]

您只需要按照以下方式实现getStructure()

protected function getStructure()
{
  return [
    'key' => 'some.nested.key',
    'favorites' => [
        'color'  => 'color',
        'number' => 'number int',
    ],
    'is_admin'       => 'adminPermission bool',
    'status'         => 'status enum:denied=0,accepted=1,pending=2',
    'important.date' => 'date date:Y-m-d',
    'cents'          => 'cents substr:1|float',
    // The `unneeded` key is not defined, so it will be ignored
    'json'           => 'json arr',
  ];
}

在上面的例子中

  • 键正是您期望的结果中的键和嵌套键
  • 值是旧键,可以包含一些转换
  • 转换与旧键之间由空格分隔,并遵循以下语法:transformation1:param1,param2|transformation2
  • 嵌套键通过点表示法定义,例如:some.nested.key
  • 数组中不存在的键将被自动忽略。

定义了新的结构后,您可以通过调用transform()方法来转换数组、对象、数组的数组或对象的数组

$transformer = new MyTransformer($data);
$transformed = $transformer->transform();

// or by using the static factory method:
$transformed = MyTransformer::from($data)->transform();

或者如果您希望将数据转换成特定的对象,可以调用transformInto()方法

$transformer = new MyTransformer($data);
$transformed = $transformer->transformInto(new DataTransferObject);

// or by using the static factory method:
$transformed = MyTransformer::from($data)->transformInto(new DataTransferObject);

标准化多个来源

有时您可能需要从不同的来源标准化数据。在这种情况下,只有来源键可能改变,而期望的键和转换保持不变。为了避免为每个来源重复代码,您可以在不指定来源键的情况下像通常一样扩展抽象转换器

use Cerbero\Transformer\AbstractTransformer;

abstract class MyTransformer extends AbstractTransformer
{
    protected function getStructure()
    {
        return [
            'key' => null,
            'favorites' => [
                'color'  => null,
                'number' => 'int',
            ],
            'is_admin'       => 'bool',
            'status'         => 'enum:denied=0,accepted=1,pending=2',
            'important.date' => 'date:Y-m-d',
            'cents'          => 'substr:1|float',
            'json'           => 'arr',
        ];
    }
}

上面的例子只定义了期望的键和相关转换,没有定义来源键。如果不需要转换,可以将null设置为值。

最后,为了将期望的键与不同来源的键进行映射,现在您可以扩展您的新转换器为每个来源,并实现方法getKeysMap()

class Source1Transformer extends MyTransformer
{
    protected function getKeysMap()
    {
        return [
            'key' => 'some.nested.key',
            'favorites' => [
                'color'  => 'color',
                'number' => 'number',
            ],
            'is_admin'       => 'adminPermission',
            'status'         => 'status',
            'important.date' => 'date',
            'cents'          => 'cents',
            'json'           => 'json',
        ];
    }
}

转换

任何函数或类方法都可以用作转换,例如trimsubstr:2Class::staticMethodNamespace\Class::instanceMethod都是有效的转换。请注意,要转换的值作为调用函数或方法的第一参数传递。

此外,此包还附带了一些内置转换

自定义转换

当函数、方法和内置转换不足以满足需求时,您可以通过向转换器添加方法来实现自己的转换,例如

protected function prefix($prefix)
{
    return $prefix . $this->value;
}

prefix现在是一个自定义转换,它接收一个前缀作为参数并将其添加到要转换的值之前。它现在可以通过使用语法prefix:foo应用,使得$prefix参数等于'foo'。上面的例子只需要一个参数,但您可以根据需要使用语法prefix:foo,bar,baz传递任意多的参数。

请注意,$this->value包含从最后应用的转换中获得的价值,所以当您传递更多转换时,该值会通过每个转换进行更新。

在自定义转换中,您还可以使用另一个有用的属性$this->item,它包含包含$this->value的数组或对象。例如,当自定义转换需要从原始项中获取另一个值以转换当前值时,这可能很有用。

有时您可能需要在不同的转换器中使用相同的自定义转换。您可以考虑将这些逻辑提取到一个类中,以便可以通过别名轻松地从任何转换器中调用它,就像内置转换一样。

use Cerbero\Transformer\Transformations\AbstractTransformation;

class PrefixTransformation extends AbstractTransformation
{
    public function apply(array $parameters)
    {
        return $parameters[0] . $this->value;
    }
}

上述自定义转换扩展了 AbstractTransformation 类,并将参数作为数组传递给 apply() 方法。由于 PrefixTransformation 遵循 名称 + Transformation 的约定,现在可以使用别名 prefix 使用,例如: prefix:foo

在转换类中,属性 $this->value$this->item 都可用,就像在转换器中定义自定义转换时一样。

您的转换类很可能有自己的命名空间,这可以通过在转换器中实现 getCustomTransformationNamespace() 方法来定义。

protected function getCustomTransformationNamespace(): string
{
    return 'My\Namespace';
}

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

测试

$ composer test

贡献

有关详细信息,请参阅 CONTRIBUTINGCODE_OF_CONDUCT

安全

如果您发现任何安全问题,请通过电子邮件 andrea.marco.sartori@gmail.com 联系我们,而不是使用问题跟踪器。

鸣谢

许可证

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