PHP code example of zahran / mapper

1. Go to this page and download the library: Download zahran/mapper library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

zahran / mapper example snippets


use Zahran\Mapper\Mapper;

$mapper  = Mapper::default();
$mapping = $mapper->compile($template);   // validate once
$mapping->map($payload);                  // reuse for every payload

use Zahran\Mapper\Mapper;

$payload = '{
    "order_id": 91,
    "customer": {"first": "Ada", "last": "Lovelace"},
    "lines": [
        {"sku": "A-1", "qty": "2", "price": "40.50"},
        {"sku": "B-7", "qty": "1", "price": "9.99"}
    ]
}';

$template = '{
    "attributes": [
        {"name": "Reference", "path": ["order_id"], "cast": {"type": "string"}},
        {
            "name": "Customer",
            "paths": [["customer", "first"], "$ ", ["customer", "last"]],
            "mutators": [{"name": "implode", "arguments": ["", "__value__"]}]
        },
        {
            "name": "Lines",
            "type": "array",
            "path": ["lines"],
            "attributes": [
                {"name": "Sku", "path": ["sku"]},
                {"name": "Quantity", "path": ["qty"], "cast": {"type": "integer"}},
                {"name": "Price", "path": ["price"], "cast": {"type": "float"}}
            ]
        }
    ]
}';

Mapper::default()->map($payload, $template);

[
    'Reference' => '91',
    'Customer'  => 'Ada Lovelace',
    'Lines'     => [
        ['Sku' => 'A-1', 'Quantity' => 2, 'Price' => 40.5],
        ['Sku' => 'B-7', 'Quantity' => 1, 'Price' => 9.99],
    ],
]

Mapper::default()->compile('{"attributes": [{"name": "A", "path": ["a"], "transform": "x"}]}');
// InvalidTemplateException: Invalid mapping template at "attributes.0":
//   "transform" is not a supported key here, expected one of: name, type, path, …

// {"order": {"customer": {"name": "Ada"}}}
{"name": "Customer", "path": ["order", "customer", "name"]}   // "Ada"

// {"rows": [{"id": 7}, {"id": 8}]}
{"name": "First", "path": ["rows", 0, "id"]}                  // 7
{"name": "Last",  "path": ["rows", -1, "id"]}                 // 8

// {"items": [{"sku": "A"}, {"sku": "B"}]}
{"name": "Skus", "path": ["items", "*", "sku"]}      // ["A", "B"]

// {"prices": {"skirt": 40, "shirt": 30}}
{"name": "Prices", "path": ["prices", "*"]}          // [40, 30]

// {"order": {"lines": [{"sku": "A"}], "gift": {"sku": "B"}}}
{"name": "Skus", "path": ["**", "sku"]}              // ["A", "B"]

// {"items": [{"sku": "A", "active": true}, {"sku": "B", "active": false}]}
{
    "name": "Skus",
    "path": ["items", {"where": {"path": ["active"], "condition_type": "eq", "value": true}}, "sku"]
}
// ["A"]

{"where": [
    {"path": ["active"], "condition_type": "eq", "value": true},
    {"path": ["stock"],  "condition_type": "gt", "value": 0}
]}

// {"scores": [10, 55, 3]}
{
    "name": "Scores",
    "type": "array",
    "path": ["scores"],
    "where": {"condition_type": "gte", "value": 10},
    "attributes": [{"name": "Value", "path": ["@"]}]
}
// [{"Value": 10}, {"Value": 55}]

// {}
{"name": "Skus", "path": ["items", "*", "sku"]}                     // []
{"name": "Skus", "path": ["items", "*", "sku"], "default": "none"}  // "none"

// {"categories": [10, 55, 3, 20]}
{"name": "Categories", "path": ["categories", [0, 1]]}
// [10, 55]

// {"categories": [10, 55]}
{"name": "Categories", "path": ["categories", [0, "$fixed", "$7", "$true", "$null"]]}
// [10, "fixed", 7, true, null]

// {}
{"name": "Name", "path": ["fullname"], "default": "John Doe"}   // "John Doe"

// {"value": null}
{"name": "Value", "path": ["value"], "default": "fallback"}     // null

{"name": "Source", "default": "static"}
{"name": "Flags",  "default": ["$true", "$null", "$7", "plain"]}   // [true, null, 7, "plain"]

// {"first": "Ada", "last": "Lovelace"}
{
    "name": "Name",
    "paths": [["first"], "$ ", ["last"]],
    "mutators": [{"name": "implode", "arguments": ["", "__value__"]}]
}
// "Ada Lovelace"

// {"net": 40, "tax": 8}
{"name": "Total", "paths": [["net"], ["tax"]], "mutators": [{"name": "array_sum"}]}
// 48

// {"items": [{"name": "Skirt"}, {"name": "Shirt"}]}
{
    "name": "Items",
    "type": "array",
    "path": ["items"],
    "attributes": [{"name": "ItemName", "path": ["name"]}]
}
// [{"ItemName": "Skirt"}, {"ItemName": "Shirt"}]

// {"orders": [{"id": 1, "lines": [{"sku": "A"}, {"sku": "B"}]}]}
{
    "name": "Orders",
    "type": "array",
    "path": ["orders"],
    "attributes": [
        {"name": "Id", "path": ["id"]},
        {
            "name": "Lines",
            "type": "array",
            "path": ["lines"],
            "attributes": [{"name": "Sku", "path": ["sku"]}]
        }
    ]
}
// [{"Id": 1, "Lines": [{"Sku": "A"}, {"Sku": "B"}]}]

"where": {"path": ["active"], "condition_type": "eq", "value": true}   // A, C
"sort":  {"path": ["price"]}                                          // B, C, A
"sort":  {"path": ["price"], "direction": "desc"}                     // A, C, B
"limit": 2                                                            // A, B
"offset": 1, "limit": 1                                               // B
"offset": -1                                                          // C

{
    "name": "Items",
    "type": "array",
    "path": ["items"],
    "where": {"path": ["active"], "condition_type": "eq", "value": true},
    "sort":  {"path": ["price"], "direction": "desc"},
    "limit": 1,
    "attributes": [{"name": "Sku", "path": ["sku"]}]
}
// [{"Sku": "A"}]

"sort": [{"path": ["group"]}, {"path": ["price"]}]

// {"items": [{"sku": "A", "price": 1}, {"sku": "A", "price": 9}, {"sku": "B", "price": 2}]}
"distinct": ["sku"]        // the A at price 1, and B
"distinct": [["sku"], ["size"]]
"distinct": true

// {"orders": [{"lines": [{"q": 1}, {"q": 9}]}, {"lines": [{"q": 5}]}]}
{
    "name": "Lines",
    "type": "array",
    "path": ["orders", "*", "lines", "*"],
    "where": {"path": ["q"], "condition_type": "gte", "value": 5},
    "attributes": [{"name": "Qty", "path": ["q"]}]
}
// [{"Qty": 9}, {"Qty": 5}]

// {"qty": "2"}
{
    "name": "Total",
    "path": ["qty"],
    "cast": {"type": "string"},
    "mutators": [{"name": "multiply", "arguments": [3]}],
    "conditions": [{"condition_type": "is_string", "then": 10}]
}
// "30"  — the condition saw the raw string, multiply saw 10, the cast saw 30

// {"tags": ["red", "green"]}
{"name": "Tags", "path": ["tags"], "mutators": [{"name": "strtoupper"}]}
// ["RED", "GREEN"]

// {"completed": true}
{"name": "Status", "path": ["completed"],
 "conditions": [{"condition_type": "eq", "value": true, "then": "done", "otherwise": "pending"}]}
// "done"

// {"score": 95}
"conditions": [
    {"condition_type": "gte", "value": 90, "then": "A"},
    {"condition_type": "eq",  "value": "A", "then": "excellent"}
]
// "excellent"

// {"name": "Ada"}
"mutators": [{"name": "strtoupper"}]                                        // "ADA"

// {"title": "hello world"}
"mutators": [{"name": "str_replace", "arguments": [" ", "-", "__value__"]}]  // "hello-world"

// {"views": 10}
"mutators": [{"name": "multiply", "arguments": [5]}]                         // 50

// {"name": "  adalovelace  "}
"mutators": [
    {"name": "trim"},
    {"name": "strtoupper"},
    {"name": "substr", "arguments": ["__value__", 0, 3]}
]
// "ADA"

Mapper::default()->compile('{"attributes": [{"name": "A", "path": ["a"], "mutators": [{"name": "shell_exec"}]}]}');
// InvalidTemplateException: … "shell_exec" is neither a registered mutator nor an allowed PHP function.

// {"price": "40.5"}
{"name": "Price", "path": ["price"], "cast": {"type": "float"}}     // 40.5

// {"when": "2024-03-09T11:30:00+00:00"}
{"name": "Day", "path": ["when"], "cast": {"type": "date", "format": "d/m/Y"}}
// "09/03/2024"

// {"items": [{"sku": "A"}, {"sku": "B"}]}
'{"type": "array", "path": ["items"], "attributes": [{"name": "Sku", "path": ["sku"]}]}'
// [["Sku" => "A"], ["Sku" => "B"]]

// [{"sku": "A"}, {"sku": "B"}]  — a root list with no path maps the payload itself
'{"type": "array", "attributes": [{"name": "Sku", "path": ["sku"]}]}'
// [["Sku" => "A"], ["Sku" => "B"]]

// {"order": {"id": 7}}
'{"path": ["order", "id"]}'                                  // 7

// {"order": {"total": "40.5"}}
'{"path": ["order", "total"], "cast": {"type": "float"}}'    // 40.5

{"name": "Sku", "path": ["sku"], "

Mapper::default()->map('{}', $template);
// InvalidPayloadException: Cannot map the payload at "Sku":
//   is 

// Cannot map the payload at "Orders.Lines.Sku": is 

$mapper = Mapper::default()->strict();

// {"count": "abc"}
{"name": "Count", "path": ["count"], "cast": {"type": "integer"}}

Mapper::default()->map($payload, $template);              // ['Count' => 0]
Mapper::default()->strict()->map($payload, $template);
// InvalidPayloadException: Cannot map the payload at "Count":
//   "abc" (string) cannot be cast to "integer" without losing its meaning.

Mapper::default()->strict()->map('{"items": "nope"}', $template);
// InvalidPayloadException: Cannot map the payload at "Items":
//   expects a list, but the payload holds string.

// {"when": "the day before never"} with a date cast
// InvalidPayloadException: Cannot map the payload at "When":
//   DateTimeImmutable::__construct(): Failed to parse time string …

use Zahran\Mapper\Condition\Predicate;

$mapper = Mapper::default()->withCondition('starts_with', new class implements Predicate {
    public function matches(mixed $value, mixed $compare): bool
    {
        return is_string($value) && is_string($compare) && str_starts_with($value, $compare);
    }
});

// {"sku": "AB-1"}
{"name": "Kind", "path": ["sku"],
 "conditions": [{"condition_type": "starts_with", "value": "AB-", "then": "internal", "otherwise": "external"}]}
// "internal"

use Zahran\Mapper\Cast\Cast;
use Zahran\Mapper\Cast\Validating;

// Implementing Validating as well is optional: it is what a strict mapper asks before
// handing the cast a value. A cast that does not implement it is trusted with anything.
$mapper = Mapper::default()->withCast('cents', new class implements Cast, Validating {
    public function cast(mixed $value, ?string $format): mixed
    {
        return (int) round(((float) $value) * 100);
    }

    public function accepts(mixed $value): bool
    {
        return is_numeric($value);
    }
});

// {"price": "40.50"} with {"cast": {"type": "cents"}}  =>  4050

use Zahran\Mapper\Mutator\Mutator;

$mapper = Mapper::default()->withMutator('suffix', new class implements Mutator {
    public function apply(mixed $value, array $arguments): mixed
    {
        return $value . ($arguments[0] ?? '');
    }
});

// {"sku": "A"} with {"mutators": [{"name": "suffix", "arguments": ["-EU"]}]}  =>  "A-EU"

$mapper = Mapper::default()->withFunctions('addslashes', 'nl2br');

$mapping = Mapper::default()->compile($template);

$mapping->map($first);
$mapping->map($second);

$mapping->mapMany(['a' => '{"name": "Ada"}', 'b' => ['name' => 'Linus']]);
// ['a' => ['Name' => 'Ada'], 'b' => ['Name' => 'Linus']]

abs array_flip array_keys array_product array_reverse array_slice array_sum array_unique
array_values base64_decode base64_encode bin2hex boolval ceil count date dechex explode
floatval floor gettype gmdate hexdec htmlspecialchars implode intdiv intval json_decode
json_encode lcfirst ltrim max mb_strlen mb_strtolower mb_strtoupper mb_substr md5 min
nl2br number_format pow preg_quote preg_replace preg_split rawurlencode round rtrim sha1
sprintf sqrt str_contains str_ends_with str_pad str_repeat str_replace str_split
str_starts_with str_word_count strip_tags strlen strrev strtolower strtotime strtoupper
strtr strval substr substr_count trim ucfirst ucwords urlencode vsprintf wordwrap