Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
odan committed Jan 26, 2021
1 parent 38b6772 commit 9c063cd
Show file tree
Hide file tree
Showing 17 changed files with 499 additions and 143 deletions.
88 changes: 80 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# selective/transformer

A strictly typed array transformer with dot access and fluent interface.
The mapped result can be used for JSON responses and many other things.
A strictly typed array transformer with dot access and fluent interface. The mapped result can be used for JSON
responses and many other things.

[![Latest Version on Packagist](https://img.shields.io/github/release/selective-php/transformer.svg)](https://packagist.org/packages/selective/transformer)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
Expand All @@ -10,6 +10,21 @@ The mapped result can be used for JSON responses and many other things.
[![Quality Score](https://img.shields.io/scrutinizer/quality/g/selective-php/transformer.svg)](https://scrutinizer-ci.com/g/selective-php/transformer/?branch=master)
[![Total Downloads](https://img.shields.io/packagist/dt/selective/transformer.svg)](https://packagist.org/packages/selective/transformer/stats)

## Table of Contents

* [Requirements](#requirements)
* [Installation](#installation)
* [Usage](#usage)
* [Transforming](#transforming)
* [Transforming list of arrays](#transforming-list-of-arrays)
* [Dot access](#dot-access)
* [Mapping rules](#mapping-rules)
* [Simple mapping rules](#simple-mapping-rules)
* [Complex mapping rules](#complex-mapping-rules)
* [Filter](#filter)
* [Custom Filter](#custom-filter)
* [License](#license)

## Requirements

* PHP 7.2+ or 8.0+
Expand All @@ -22,6 +37,8 @@ composer require selective/transformer

## Usage

### Transforming

Sample data:

```php
Expand All @@ -32,8 +49,6 @@ $data = [
];
```

### Minimal example

```php
<?php

Expand All @@ -57,10 +72,65 @@ The result:
];
```

### Dot access
### Transforming list of arrays

You can use a method "toArrays" to transform a list of arrays.

This can be useful if you want to transform a resultset from a database query, or a response payload from an API.

**Example:**

```php
$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);
```

The result:

You can copy any data from the source array to any sub-element of the destination array
using the dot-syntax.
```php
[
[
'id' => 100,
'first_name' => 'Sally',
'enabled' => true,
],
[
'id' => 101,
'first_name' => 'Max',
'last_name' => 'Doe',
'phone' => '+123456789',
'enabled' => false,
],
]
```

## Dot access

You can copy any data from the source array to any sub-element of the destination array using the dot-syntax.

```php
<?php
Expand All @@ -70,6 +140,8 @@ $transformer->map('firstName', 'address.first_name')
->map('invoice.items', 'root.sub1.sub2.items');
```

## Mapping Rules

### Simple mapping rules

Using strings, separated by `|`, to define a filter chain:
Expand Down Expand Up @@ -170,7 +242,7 @@ $transformer->rule()->callback(
);
```

## Custom filters
### Custom Filter

You can also add your own custom filter:

Expand Down
93 changes: 72 additions & 21 deletions src/ArrayTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
use Selective\Transformer\Filter\NumberFormatFilter;
use Selective\Transformer\Filter\StringFilter;

/**
* Transformer.
*/
final class ArrayTransformer
{
/**
Expand All @@ -25,35 +28,52 @@ final class ArrayTransformer
*/
private $converter;

/**
* @var string[]
*/
private $internalFilters = [
'string' => StringFilter::class,
'blank-to-null' => BlankToNullFilter::class,
'boolean' => BooleanFilter::class,
'integer' => IntegerFilter::class,
'float' => FloatFilter::class,
'number' => NumberFormatFilter::class,
'date' => DateTimeFilter::class,
'array' => ArrayFilter::class,
'callback' => CallbackFilter::class,
];

/**
* The constructor.
*/
public function __construct()
{
$this->converter = new ArrayValueConverter();
$this->registerFilter('string', StringFilter::class);
$this->registerFilter('blank-to-null', BlankToNullFilter::class);
$this->registerFilter('boolean', BooleanFilter::class);
$this->registerFilter('integer', IntegerFilter::class);
$this->registerFilter('float', FloatFilter::class);
$this->registerFilter('number', NumberFormatFilter::class);
$this->registerFilter('date', DateTimeFilter::class);
$this->registerFilter('array', ArrayFilter::class);
$this->registerFilter('callback', CallbackFilter::class);

foreach ($this->internalFilters as $name => $class) {
$this->registerFilter($name, new $class());
}
}

/**
* @param string $string
* @param callable|string $filter
* Register custom filter.
*
* @param string $name The name
* @param callable $filter The filter callback
*/
public function registerFilter(string $string, $filter): void
public function registerFilter(string $name, callable $filter): void
{
$this->converter->registerFilter($string, $filter);
$this->converter->registerFilter($name, $filter);
}

/**
* @param string $destination
* @param string $source
* @param ArrayTransformerRule|string|null $rule
* Add mapping rule.
*
* @param string $destination The destination element
* @param string $source The source element
* @param ArrayTransformerRule|string|null $rule The rule
*
* @return $this
* @return $this The transformer
*/
public function map(string $destination, string $source, $rule = null): self
{
Expand All @@ -68,11 +88,23 @@ public function map(string $destination, string $source, $rule = null): self
return $this;
}

/**
* Create transformer rule.
*
* @return ArrayTransformerRule The rule
*/
public function rule(): ArrayTransformerRule
{
return new ArrayTransformerRule();
}

/**
* Convert rule string to rule object.
*
* @param string $rules The rules, separated by '|'
*
* @return ArrayTransformerRule The rule object
*/
private function ruleFromString(string $rules): ArrayTransformerRule
{
$rule = $this->rule();
Expand All @@ -90,10 +122,12 @@ private function ruleFromString(string $rules): ArrayTransformerRule
}

/**
* @param array<mixed> $source
* @param array<mixed> $target
* Transform array to array.
*
* @param array<mixed> $source The source
* @param array<mixed> $target The target (optional)
*
* @return array<mixed>
* @return array<mixed> The result
*/
public function toArray(array $source, array $target = []): array
{
Expand All @@ -105,7 +139,7 @@ public function toArray(array $source, array $target = []): array
$value = $this->converter->convert($value, $rule);

if ($value === null && !$rule->isRequired()) {
// Don't add item to result
// Skip item
continue;
}

Expand All @@ -114,4 +148,21 @@ public function toArray(array $source, array $target = []): array

return $targetData->export();
}

/**
* Transform list of arrays to list of arrays.
*
* @param array<mixed> $source The source
* @param array<mixed> $target The target (optional)
*
* @return array<mixed> The result
*/
public function toArrays(array $source, array $target = []): array
{
foreach ($source as $item) {
$target[] = $this->toArray($item);
}

return $target;
}
}
44 changes: 0 additions & 44 deletions src/ArrayTransformerFilter.php

This file was deleted.

51 changes: 51 additions & 0 deletions src/ArrayTransformerFilterItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Selective\Transformer;

/**
* Filter.
*/
final class ArrayTransformerFilterItem
{
/**
* @var string
*/
private $name;

/**
* @var array<mixed>
*/
private $arguments;

/**
* The constructor.
*
* @param string $name The filter to apply
* @param array<mixed> $arguments The parameters for the filter
*/
public function __construct(string $name, array $arguments = [])
{
$this->name = $name;
$this->arguments = $arguments;
}

/**
* The filter to apply.
*
* @return string The name
*/
public function getName(): string
{
return $this->name;
}

/**
* Get filter parameters.
*
* @return array<mixed> The params
*/
public function getArguments(): array
{
return $this->arguments;
}
}
Loading

0 comments on commit 9c063cd

Please sign in to comment.