emulgeator/数组到类映射器

一个可以将多级数组转换为类对象的库

1.1.1 2024-04-12 09:53 UTC

README

这是一个简单的库,它可以自动将给定的多维数组映射到给定的类。

入门

安装

运行 composer require emulgeator/array-to-class-mapper 将此库添加为项目依赖项

用法

简单标量类型映射

use Emul\ArrayToClassMapper\MapperFactory;

class DTO
{
    private int $id;

    private float $value;

    public function __construct() {
        // Constructor wont be called
    }
}

$arrayToMap = [
    'id' => '1',
    'value' => '1.2'
];

$mapper = (new MapperFactory())->getMapper();

/** @var DTO $dto */
$dto = $mapper->map($arrayToMap, DTO::class);

如您所见,该库将数组中的值转换为相应的类型。例如:$dto->id 将确实是一个整数。

映射器通过检查属性的类型来完成此操作。如果未设置,它将尝试从 DocBlock 中获取此信息

类映射

use Emul\ArrayToClassMapper\MapperFactory;

require_once 'vendor/autoload.php';

class InnerDTO
{
    private string $key;
    private string $value;
}

class DTO
{
    private InnerDTO $inner;
}

$arrayToMap = [
    'inner' => [
        'key'   => 'first_key',
        'value' => 'value'
    ]
];

$mapper = (new MapperFactory())->getMapper();

/** @var DTO $dto */
$dto = $mapper->map($arrayToMap, DTO::class);

复杂类型映射

对于复杂类型,可以使用 DocBlock 和类型提示。请参见前面示例的修改版本,其中包含一系列内部对象

use Emul\ArrayToClassMapper\MapperFactory;

require_once 'vendor/autoload.php';

class InnerDTO
{
    private string $key;
    private string $value;
}

class DTO
{
    private int $id;

    /** @var InnerDTO[] */
    private array $inner = [];
}

$arrayToMap = [
    'id' => 1,
    'inner' => [
        [
            'key'   => 'first_key',
            'value' => 'value'
        ],
        [
            'key'   => 'second_key',
            'value' => 'value'
        ],
    ]
];

$mapper = (new MapperFactory())->getMapper();

/** @var DTO $dto */
$dto = $mapper->map($arrayToMap, DTO::class);

为特定类型定义自定义映射器

如果无法通过简单转换存储的值来进行数据映射,则可以设置自定义映射器

use Carbon\Carbon;
use Carbon\CarbonInterface;
use Emul\ArrayToClassMapper\MapperFactory;

require_once 'vendor/autoload.php';

class InnerDTO
{
    private string $key;
    private string $value;

    public function __construct(string $keyPrefix, string $key, string $value)
    {
        $this->key   = $keyPrefix . $key;
        $this->value = $value;
    }
}

class DTO
{
    private int $id;

    /** @var InnerDTO[] */
    private array $values;
}

$arrayToMap = [
    'id'        => 1,
    'values' => [
        [
            'key' => 'first',
            'value' => '1'
        ],
    ],
];

$mapper = (new MapperFactory())->getMapper();

$innerDTOMapper = \Closure::fromCallable(function (array $data) {
    return new InnerDTO('prefix_', $data['key'], $data['value']);
});

$mapper->addCustomMapper(InnerDTO::class, $innerDTOMapper);
/** @var DTO $dto */
$dto = $mapper->map($arrayToMap, DTO::class);

如果自定义类型在数组中,则也是如此;但是在这种情况下,映射器函数将接收原始子数组


限制

该库目前无法导入和自动加载在 DocBlock 中定义的类。以下示例将无法工作,因为该类既未导入,我们也不知道其完全限定名(FQCN)

/** @var Value[] */
private array $values = [];

要修复此问题,您需要使用类的 FQCN

/** @var \NameSpace\Value[] */
private array $values = [];