awesome-php
awesome-php copied to clipboard
Add Schemator to Architectural section
Schematic data mapper ·

Schemator is a tool for converting nested data structures (any composition of associative arrays, non-associative arrays and objects) according to the given conversion schema.
Examples
Simple usage
use Smoren\Schemator\Factories\SchematorFactory;
$input = [
'id' => 100,
'name' => 'Oxford',
'country' => [
'id' => 10,
'name' => 'UK',
'neighbours' => ['Ireland', 'Sweden', 'France'],
'capitals' => [
'lnd' => 'London',
'edb' => 'Edinburgh',
],
],
'streets' => [
[
'id' => 1000,
'name' => 'Woodstock Rd',
'houses' => [1, 5, 9],
],
[
'id' => 1002,
'name' => 'Banbury Rd',
'houses' => [22, 35, 49],
],
[
'id' => 1003,
'name' => 'Beamont St',
'houses' => [11, 12, 15],
],
],
'lnd_path' => 'country.capitals.lnd',
];
$schema = [
'city_id' => 'id',
'city_name' => 'name',
'city_street_names' => 'streets.*.name',
'country_id' => 'country.id',
'country_name' => 'country.name',
'country_neighbours' => 'country.neighbours',
'country_neighbour' => 'country.neighbours',
'country_first_capital' => 'country.capitals.lnd',
'country_second_capital' => 'country.capitals.edb',
'country_data.country_id' => 'country.id',
'country_data.country_name' => 'country.name',
];
$schemator = SchematorFactory::create();
$output = $schemator->convert($input, $schema);
print_r($output);
/* Array
(
[city_id] => 100
[city_name] => Oxford
[city_street_names] => Array
(
[0] => Woodstock Rd
[1] => Banbury Rd
[2] => Beamont St
)
[country_id] => 10
[country_name] => UK
[country_neighbours] => Array
(
[0] => Ireland
[1] => Sweden
[2] => France
)
[country_neighbour] => Array
(
[0] => Ireland
[1] => Sweden
[2] => France
)
[country_first_capital] => London
[country_second_capital] => Edinburgh
[country_data] => Array
(
[country_id] => 10
[country_name] => UK
)
)
*/
Using base filters
use Smoren\Schemator\Factories\SchematorFactory;
use Smoren\Schemator\Filters\BaseFiltersStorage;
$input = [
'id' => 100,
'name' => 'Oxford',
'country' => [
'id' => 10,
'name' => 'UK',
'neighbours' => ['Ireland', 'Sweden', 'France'],
'capitals' => [
'lnd' => 'London',
'edb' => 'Edinburgh',
],
],
'streets' => [
[
'id' => 1000,
'name' => 'Woodstock Rd',
'houses' => [1, 5, 9],
],
[
'id' => 1002,
'name' => 'Banbury Rd',
'houses' => [22, 35, 49],
],
[
'id' => 1003,
'name' => 'Beamont St',
'houses' => [11, 12, 15],
],
],
'lnd_path' => 'country.capitals.lnd',
];
$schema = [
'city_street_names.all' => ['streets.*.name', ['implode', ', ']],
'city_street_names.sorted' => ['streets.*.name', ['sort'], ['implode', ', ']],
'city_street_names.filtered' => ['streets.*.name', ['filter', fn (string $candidate) => strpos($candidate, 'Ban') !== false]],
'lnd' => ['lnd_path', ['path']],
'city_street_houses' => ['streets.*.houses', ['flatten']],
];
$schemator = SchematorFactory::create();
$output = $schemator->convert($input, $schema);
print_r($output);
/*
Array
(
[city_street_names] => Array
(
[all] => Woodstock Rd, Banbury Rd, Beamont St
[sorted] => Banbury Rd, Beamont St, Woodstock Rd
[filtered] => Array
(
[0] => Banbury Rd
)
)
[lnd] => London
[city_street_houses] => Array
(
[0] => 1
[1] => 5
[2] => 9
[3] => 22
[4] => 35
[5] => 49
[6] => 11
[7] => 12
[8] => 15
)
)
*/
Using custom filters
use Smoren\Schemator\Factories\SchematorFactory;
use Smoren\Schemator\Interfaces\FilterContextInterface;
$schemator = SchematorFactory::createBuilder()
->withFilters([
'startsWith' => function (FilterContextInterface $context, string $start) {
return array_filter($context->getSource(), function (string $candidate) use ($start) {
return strpos($candidate, $start) === 0;
});
},
])
->get();
$input = [
'streets' => ['Woodstock Rd', 'Banbury Rd', 'Beamont St'],
];
$schema = [
'street_names' => ['streets', ['startsWith', 'T'], ['implode', ', ']],
];
$output = $schemator->convert($input, $schema);
print_r($output);
/*
Array
(
[street_names] => Woodstock Rd, Beamont St
)
*/
It doesn't seem to be widely used yet.
Thank you @alexkart for your comment. I agree that the repository is not widely popular at the moment, but I hope that its usefulness will be a more important factor in deciding whether to add it to the list.
Looks to me like this is a bit more powerful version of https://github.com/jolicode/automapper In general, I am a big fan of the idea of having a schema to map from incoming data (e.g. API call) to nested (DTO) objects.
I was working on sth even more powerful that auto-defines itself based on the data structure of the example array, creating the schema on its own (with only few customizations necessary), generating the necessary PHP classes and having it all up and ready < 1min: https://github.com/dereuromark/cakephp-dto Still framework specific, but it could be made more generic, if people are interested in the idea and helping out.
That said, I think having at least one useful datamapper on its own listed here sounds like a good idea. Do we have already some listed?
哈喽