selective/transformer

一个严格类型的数组变压器,具有点访问、流畅的接口和过滤器。

1.3.0 2023-09-09 21:48 UTC

This package is auto-updated.

Last update: 2024-08-28 21:18:28 UTC


README

一个具有点访问和流畅接口的严格类型数组变压器。映射结果可用于JSON响应和其他许多用途。

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

目录

要求

  • PHP 8.1+

安装

composer require selective/transformer

介绍

此Transformer组件提供了将数组或对象中的数组值映射、转换和循环到另一个数组的函数。

使用简单的PHP转换复杂数据时,通过大量类型转换、if条件和通过foreach()循环数据来实现。这导致循环复杂度和嵌套深度非常高,因此“代码评分”很差。

之前:条件:9,路径:256,CRAP分数:9

点击展开!

之后:条件:1,路径:1,CRAP分数:1

点击展开!

用例

在构建API时,人们通常会直接从数据库中抓取东西并传递给json_encode()。这可能适用于“简单”API,但如果它们被公众使用或被移动应用使用,那么这很快会导致输出不一致。Transformer能够创建源数据和输出之间的“屏障”,因此架构更改不会影响用户。

Transformer还可以非常有效地将任何类型的数据库结果集(例如,来自PDO的)放入新的数据结构中。

用例并不限于。

点访问

您可以使用点符号将源数组中的任何数据复制到目标数组的任何子元素中。

<?php
use Selective\Transformer\ArrayTransformer;

$transformer = new ArrayTransformer();

$transformer->map('firstName', 'address.first_name')
    ->map('lastName', 'address.last_name')
    ->map('invoice.items', 'root.sub1.sub2.items');

// ...

对象访问

您可以使用点符号访问对象的属性。

use Selective\Transformer\ArrayTransformer;

$transformer = new ArrayTransformer();

$transformer->map('bar1', 'foo.bar', 'string')
    ->map('bar2', 'foo.bar2.0', 'string')
    ->map('sub.sub2.sub3', 'foo.bar2.1', 'string');

$user = new stdClass();
$user->foo = new stdClass();
$user->foo->bar = 'Hello Bar';
$user->foo->bar2 = [
    0 => 'Test 0',
    1 => 'Test 1',
];

$result = $transformer->toArray((array)$user);

结果

[
    'bar1' => 'Hello Bar',
    'bar2' => 'Test 0',
    'sub' => [
        'sub2' => [
            'sub3' => 'Test 1',
        ],
    ],
];

转换

转换数组

为了简单起见,这个示例被组装成一个文件。实际上,您会将管理器初始化、数据收集和JSON转换分散到应用程序的各个部分。

示例数据

$data = [
    'first_name' => 'Sally',
    'last_name' => '',
    'email' => 'sally@example.com',
];
<?php

use Selective\Transformer\ArrayTransformer;

$transformer = new ArrayTransformer();

$transformer->map('firstName', 'first_name')
    ->map('lastName', 'last_name')
    ->map('email', 'email');
    
$result = $transformer->toArray($data);

结果

[
    'firstName' => 'Sally',
    'email' => 'sally@example.com',
];

转换数组列表

toArrays方法可以将数组列表转换为。

如果您想将数据库查询的结果集或API的响应有效负载转换为,这可能很有用。

示例

$transformer = new ArrayTransformer();

$transformer->map('id', 'id', $transformer->rule()->integer())
    ->map('first_name', 'first_name', $transformer->rule()->string())
    ->map('last_name', 'last_name', $transformer->rule()->string())
    ->map('phone', 'phone', $transformer->rule()->string())
    ->map('enabled', 'enabled', $transformer->rule()->boolean());

$rows = [];
$rows[] = [
    'id' => '100',
    'first_name' => 'Sally',
    'last_name' => '',
    'phone' => null,
    'enabled' => '1',
];

$rows[] = [
    'id' => '101',
    'first_name' => 'Max',
    'last_name' => 'Doe',
    'phone' => '+123456789',
    'enabled' => '0',
];

$result = $transformer->toArrays($rows);

结果

[
    [
        'id' => 100,
        'first_name' => 'Sally',
        'enabled' => true,
    ],
    [
        'id' => 101,
        'first_name' => 'Max',
        'last_name' => 'Doe',
        'phone' => '+123456789',
        'enabled' => false,
    ],
]

映射规则

简单映射规则

使用由|分隔的字符串来定义过滤器链

<?php

use Selective\Transformer\ArrayTransformer;

$transformer = new ArrayTransformer();

$transformer->map('firstName', 'first_name', 'string|required')
    ->map('lastName', 'last_name', 'string|required')
    ->map('email', 'email', 'string|required');

$data = [
    'first_name' => 'Sally',
    'last_name' => '',
    'email' => 'sally@example.com',
];
    
$result = $transformer->toArray($data);

由于lastName为空但必填,结果如下所示

[
    'firstName' => 'Sally',
    'lastName' => '',
    'email' => 'sally@example.com',
];

复杂映射规则

对于更复杂的映射规则,有一个流畅的接口可用。要创建新规则,请使用rule方法,并将其作为第三个参数传递给map方法。

<?php

use Selective\Transformer\ArrayTransformer;

$transformer = new ArrayTransformer();

$transformer->map('firstName', 'first_name', $transformer->rule()->string()->required())
    ->map('lastName', 'last_name', $transformer->rule()->string()->required())
    ->map('email', 'email', $transformer->rule()->string()->required());

$data = [
    'first_name' => 'Sally',
    'last_name' => '',
    'email' => 'sally@example.com',
];

$result = $transformer->toArray($data);

由于lastName为空但必填,结果如下所示

[
    'firstName' => 'Sally',
    'lastName' => '',
    'email' => 'sally@example.com',
];

过滤器

大多数过滤器都直接作为方法可用。

// Cast value to string, convert blank to null
$transformer->rule()->string();

// Cast value to string, allow blank string ''
$transformer->rule()->string(true);

// Cast value to int
$transformer->rule()->integer();

// Cast value to float
$transformer->rule()->float();

// Cast value to bool
$transformer->rule()->boolean();

// Cast value to datetime string, default: Y-m-d H:i:s
$transformer->rule()->date();

// Cast value to date string
$transformer->rule()->date('Y-m-d');

// Format value to number using the number_format function
$transformer->rule()->number();

// Format value to number with a custom number format
$transformer->rule()->number(2, '.', ',');

// Cast value to array
$transformer->rule()->array();

// Cast value using a custom callback function
$transformer->rule()->callback(
    function ($value) {
        return 'My custom value: ' . $value;
    }
);

// Set fixed value
$transformer->set('bar.0.item', 'default-value');

// Apply transformation to array item
$transformer->rule()->transform(
    function (ArrayTransformer $transformer) {
        $transformer
            ->map('id', 'id', 'integer')
            ->map('first_name', 'first_name', 'string');
    }
);

// Apply transformation to a list of arrays
$transformer->rule()->transformList(
    function (ArrayTransformer $transformer) {
        $transformer
            ->map('id', 'id', 'integer')
            ->map('first_name', 'first_name', 'string');
       }
);

自定义过滤器

您还可以添加自己的自定义过滤器

$transformer = new ArrayTransformer();

// Add a trim filter using the native trim function
$transformer->registerFilter('trim', 'trim');

// Usage
$transformer->map('destination', 'source', 'trim');

// or

$transformer->map('destination', 'source', $transformer->rule()->filter('trim'));

使用回调添加自定义过滤器

$transformer = new ArrayTransformer();

$transformer->registerFilter(
    'custom1',
    function ($value) {
        return 'Custom value: ' . $value;
    }
);

// Usage
$transformer->map('destination', 'source', 'custom1');

// or

$transformer->map('destination', 'source', $transformer->rule()->filter('custom1'));

// It is possible to chain multiple filters
$transformer->map(
    'destination',
    'source',
    $transformer->rule()->filter('custom1')->filter('trim')->required()->default('example')
);

使用映射特定回调定义自定义过滤器

$transformer = new ArrayTransformer();

$transformer->map(
    'destination',
    'source',
    $transformer->rule()->callback(
        function ($value) {
            return 'Callback value: ' . $value;
        }
    )
);

还有更多可注册的过滤器类可用

use Selective\Transformer\Filter\SprintfFilter;

$transformer = new ArrayTransformer();

// Convert the value using the sprintf function
$transformer->registerFilter('sprintf', new SprintfFilter());

// Usage
$transformer->map('destination', 'source', $transformer->rule()->filter('sprintf', 'Count: %d'));

您还可以实现并注册自己的过滤器类。

示例

JSON转换

您可以使用自己的JSON组件或仅使用本地的json_encode函数。

// Turn all of that into a JSON string
$json = (string)json_encode($transformer->toArray($data));

将JSON写入PSR-7响应对象

// Set correct header
$response = $response->withHeader('Content-Type', 'application/json');

// Write json string to the response body
$response->getBody()->write($json);

return $response;

PDO结果集转换

use Selective\Transformer\ArrayTransformer;

$pdo = new PDO($dsn, $username, $password, $options);

$statement = $pdo->query('SELECT id, username, first_name FROM users');
$rows = $statement->fetchAll();

$transformer = new ArrayTransformer();

$transformer->map('id', 'id', 'integer')
    ->map('username', 'username', 'string|required')
    ->map('first_name', 'first_name', 'string|required');
    
$result = $transformer->toArrays($rows);

结果

[
    [
        'id' => 1,
        'username' => 'sally',
        'first_name' => 'Sally',
    ]  
    // ... 
];

类似包

许可

MIT 许可协议。更多信息请参阅许可文件