PHPackages                             elaitech/data-mapper - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. elaitech/data-mapper

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

elaitech/data-mapper
====================

Elaitech DataMapper - A reusable data mapping and transformation component for Laravel.

0.0.1(3mo ago)04MITPHPPHP ^8.4

Since Feb 15Pushed 3mo agoCompare

[ Source](https://github.com/medab123/data-mapper)[ Packagist](https://packagist.org/packages/elaitech/data-mapper)[ RSS](/packages/elaitech-data-mapper/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (5)Versions (2)Used By (0)

📦 Elaitech DataMapper
=====================

[](#-elaitech-datamapper)

A reusable **data mapping and transformation** library for Laravel 12. Maps source fields to target fields with chained value transformers, dot-notation and wildcard field extraction, value mapping lookups, and full support for both associative and indexed (header-based) data rows.

> **Namespace:** `Elaitechx\DataMapper`
> **Requires:** PHP 8.4+ · Laravel 12 · `spatie/laravel-data` ^4.19

---

📖 Table of Contents
-------------------

[](#-table-of-contents)

- [Installation](#-installation)
- [Architecture](#-architecture)
- [Quick Start](#-quick-start)
- [Core Components](#-core-components)
- [Built-in Transformers](#-built-in-transformers)
- [Field Extraction](#-field-extraction)
- [Value Mapping](#-value-mapping)
- [Creating Custom Transformers](#-creating-custom-transformers)
- [DTOs](#-dtos)
- [Contracts](#-contracts)
- [Testing](#-testing)
- [License](#-license)

---

🚀 Installation
--------------

[](#-installation)

### As a local Composer package

[](#as-a-local-composer-package)

In your root `composer.json`, add the package as a path repository:

```
{
    "repositories": [
        {
            "type": "path",
            "url": "./packages/data-mapper",
            "options": { "symlink": true }
        }
    ],
    "require": {
        "elaitech/data-mapper": "@dev"
    }
}
```

Then install:

```
composer update elaitech/data-mapper
```

The `DataMapperServiceProvider` is auto-discovered by Laravel. It registers:

- `DataMapperInterface` → `DataMapperService` (binding)
- `ValueTransformer` — singleton with 10 built-in transformers
- `FieldExtractor` — singleton

---

🏗 Architecture
--------------

[](#-architecture)

```
src/
├── DataMapperService.php          # Main entry point — maps data rows using rules
├── DataMapperServiceProvider.php  # Laravel auto-discovery provider
├── FieldExtractor.php             # Dot-notation & wildcard field extraction
├── ValueTransformer.php           # Transformer registry & value transformation engine
│
├── Contracts/
│   ├── DataMapperInterface.php    # Main service contract
│   └── TransformerInterface.php   # Interface for all transformers
│
├── DTO/
│   ├── MappingConfigurationData.php  # Input: data + rules + headers
│   ├── MappingRuleData.php           # Single mapping rule definition
│   └── DataMappingResultData.php     # Output: mapped data + errors
│
└── Transformers/                  # 10 built-in transformers
    ├── NoneTransformer.php
    ├── TrimTransformer.php
    ├── UpperTransformer.php
    ├── LowerTransformer.php
    ├── IntegerTransformer.php
    ├── FloatTransformer.php
    ├── BooleanTransformer.php
    ├── DateTransformer.php
    ├── ArrayFirstTransformer.php
    └── ArrayJoinTransformer.php

```

---

⚡ Quick Start
-------------

[](#-quick-start)

```
use Elaitech\DataMapper\Contracts\DataMapperInterface;
use Elaitech\DataMapper\DTO\MappingConfigurationData;
use Elaitech\DataMapper\DTO\MappingRuleData;
use Spatie\LaravelData\DataCollection;

$mapper = app(DataMapperInterface::class);

$config = new MappingConfigurationData(
    data: [
        ['name' => 'John Doe', 'email' => 'john@example.com', 'age' => '30'],
        ['name' => 'Jane Smith', 'email' => 'jane@example.com', 'age' => '25'],
    ],
    mappingRules: MappingRuleData::collection([
        new MappingRuleData(
            sourceField: 'name',
            targetField: 'full_name',
            transformation: 'trim',
        ),
        new MappingRuleData(
            sourceField: 'email',
            targetField: 'contact_email',
            transformation: 'lower',
        ),
        new MappingRuleData(
            sourceField: 'age',
            targetField: 'user_age',
            transformation: 'integer',
        ),
    ]),
);

$result = $mapper->map($config);

// $result->data = [
//     ['full_name' => 'John Doe', 'contact_email' => 'john@example.com', 'user_age' => 30],
//     ['full_name' => 'Jane Smith', 'contact_email' => 'jane@example.com', 'user_age' => 25],
// ]
// $result->errors = []
```

---

🧩 Core Components
-----------------

[](#-core-components)

### `DataMapperService`

[](#datamapperservice)

The main service class. Implements `DataMapperInterface`.

```
public function map(MappingConfigurationData $config): DataMappingResultData
```

**Behaviour:**

- Automatically detects whether rows are **associative** (`['name' => 'John']`) or **indexed** (`['John', 'john@example.com']`)
- For indexed rows, uses the `headers` array to resolve field positions
- Wraps each row in a try/catch — failed rows are captured as errors, not exceptions
- Returns `DataMappingResultData` with mapped data and any per-row errors

### `FieldExtractor`

[](#fieldextractor)

Extracts values from data using:

PatternExampleDescription**Direct access**`name`Top-level field**Dot notation**`address.city`Nested field traversal**Wildcard**`items.*.name`Extract from all array elements```
$extractor = app(FieldExtractor::class);

$data = [
    'user' => ['profile' => ['name' => 'John']],
    'items' => [
        ['name' => 'A', 'price' => 10],
        ['name' => 'B', 'price' => 20],
    ],
];

$extractor->extractValue($data, 'user.profile.name');  // 'John'
$extractor->extractArrayValues($data, 'items.*.name'); // ['A', 'B']
$extractor->hasField($data, 'user.profile.name');       // true
```

### `ValueTransformer`

[](#valuetransformer)

The transformer registry and execution engine. Manages all registered transformers and applies transformation chains.

```
$transformer = app(ValueTransformer::class);

// Check available transformers
$transformer->getTransformerOptions(); // ['none' => 'None', 'trim' => 'Trim', ...]

// Register a custom transformer
$transformer->registerTransformer(new MyCustomTransformer());
```

**Transformation flow:**

1. Check if value is empty → return `defaultValue` (unless it's an array transformer)
2. Apply **value mapping** if configured (lookup table)
3. Apply **transformer** (type conversion, formatting)
4. If result is empty string and `defaultValue` is set → return `defaultValue`

---

🔧 Built-in Transformers
-----------------------

[](#-built-in-transformers)

NameLabelDescriptionRequires Format`none`NonePass-through, no transformation❌`trim`TrimRemove leading/trailing whitespace❌`upper`UppercaseConvert to UPPERCASE❌`lower`LowercaseConvert to lowercase❌`integer`IntegerCast to `int`❌`float`FloatCast to `float` with precision control✅ (decimals)`boolean`BooleanCast to `bool` (handles `"true"`, `"1"`, `"yes"`, etc.)❌`date`DateParse and reformat dates✅ (date format)`array_first`Array FirstExtract first element from array❌`array_join`Array JoinJoin array elements with separator✅ (separator)---

🗺 Field Extraction
------------------

[](#-field-extraction)

### Dot Notation

[](#dot-notation)

Access nested fields in associative arrays:

```
// Source data
['address' => ['street' => '123 Main St', 'city' => 'NYC']]

// Mapping rule: sourceField = 'address.city'
// Extracted value: 'NYC'
```

### Wildcard Notation

[](#wildcard-notation)

Extract values from arrays of objects:

```
// Source data
['images' => [
    ['url' => 'img1.jpg', 'alt' => 'First'],
    ['url' => 'img2.jpg', 'alt' => 'Second'],
]]

// Mapping rule: sourceField = 'images.*.url'
// Extracted value: ['img1.jpg', 'img2.jpg']
```

### Indexed (Header-Based) Rows

[](#indexed-header-based-rows)

For data without keys (e.g., CSV rows), provide headers:

```
$config = new MappingConfigurationData(
    data: [
        ['John', 'john@example.com', '30'],
        ['Jane', 'jane@example.com', '25'],
    ],
    mappingRules: MappingRuleData::collection([
        new MappingRuleData(sourceField: 'name', targetField: 'full_name'),
        new MappingRuleData(sourceField: 'email', targetField: 'contact'),
    ]),
    headers: ['name', 'email', 'age'],
);
```

---

🔀 Value Mapping
---------------

[](#-value-mapping)

Map specific values using a lookup table. Useful for code-to-label conversions:

```
new MappingRuleData(
    sourceField: 'condition_code',
    targetField: 'condition',
    transformation: 'none',
    valueMapping: [
        ['from' => '0', 'to' => 'Used'],
        ['from' => '1', 'to' => 'New'],
        ['from' => '2', 'to' => 'Refurbished'],
    ],
);

// Input: '1' → Output: 'New'
// Input: '0' → Output: 'Used'
// Input: '99' → Output: '99' (unmapped values pass through)
```

Value mapping is applied **before** the transformer, so you can combine both:

```
new MappingRuleData(
    sourceField: 'status',
    targetField: 'display_status',
    transformation: 'upper',
    valueMapping: [['from' => '1', 'to' => 'active'], ['from' => '0', 'to' => 'inactive']],
);
// Input: '1' → mapped to 'active' → transformed to 'ACTIVE'
```

---

🛠 Creating Custom Transformers
------------------------------

[](#-creating-custom-transformers)

Implement the `TransformerInterface`:

```
use Elaitech\DataMapper\Contracts\TransformerInterface;

final class SlugTransformer implements TransformerInterface
{
    public function getName(): string
    {
        return 'slug';
    }

    public function getLabel(): string
    {
        return 'Slugify';
    }

    public function getDescription(): string
    {
        return 'Converts text to URL-friendly slug';
    }

    public function transform($value, ?string $format = null, $defaultValue = null)
    {
        if ($value === null) {
            return $defaultValue;
        }

        return \Illuminate\Support\Str::slug((string) $value);
    }

    public function requiresFormat(): bool
    {
        return false;
    }
}
```

Register it:

```
$transformer = app(ValueTransformer::class);
$transformer->registerTransformer(new SlugTransformer());
```

Or register in a service provider for global availability:

```
public function boot(): void
{
    $this->app->make(ValueTransformer::class)
        ->registerTransformer(new SlugTransformer());
}
```

---

📋 DTOs
------

[](#-dtos)

### `MappingConfigurationData`

[](#mappingconfigurationdata)

Input to the mapper:

PropertyTypeDescription`data``array`Array of rows to map`mappingRules``DataCollection`Mapping rules to apply`headers``?array`Column headers for indexed rows### `MappingRuleData`

[](#mappingruledata)

A single field mapping rule:

PropertyTypeDefaultDescription`sourceField``string`—Source field name (supports dot/wildcard notation)`targetField``string`—Target field name in output`transformation``string``'none'`Transformer name to apply`isRequired``bool``false`Throw if source field is missing`defaultValue``mixed``null`Fallback for empty values`format``?string``null`Format parameter for transformers (e.g., date format)`valueMapping``?array``null`Value lookup table (`[['from' => ..., 'to' => ...]]`)### `DataMappingResultData`

[](#datamappingresultdata)

Output from the mapper:

PropertyTypeDescription`data``array`Successfully mapped rows`errors``array`Per-row error messages---

📜 Contracts
-----------

[](#-contracts)

### `DataMapperInterface`

[](#datamapperinterface)

```
interface DataMapperInterface
{
    public function map(MappingConfigurationData $config): DataMappingResultData;
}
```

### `TransformerInterface`

[](#transformerinterface)

```
interface TransformerInterface
{
    public function getName(): string;
    public function getLabel(): string;
    public function getDescription(): string;
    public function transform($value, ?string $format = null, $defaultValue = null);
    public function requiresFormat(): bool;
}
```

---

🧪 Testing
---------

[](#-testing)

```
# From the package directory
./vendor/bin/phpunit

# From the root project
php artisan test
```

---

📦 Dependencies
--------------

[](#-dependencies)

PackageVersionPurpose`illuminate/support`^12.0Laravel framework support`spatie/laravel-data`^4.19Typed DTOs with auto-mapping---

📄 License
---------

[](#-license)

MIT

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance82

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

93d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/783175c2d587807f6f3d27f40a857f087f67631b74e5b902ca85e2d3ae64a9e5?d=identicon)[medab123](/maintainers/medab123)

---

Top Contributors

[![medab123](https://avatars.githubusercontent.com/u/51244814?v=4)](https://github.com/medab123 "medab123 (5 commits)")

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/elaitech-data-mapper/health.svg)

```
[![Health](https://phpackages.com/badges/elaitech-data-mapper/health.svg)](https://phpackages.com/packages/elaitech-data-mapper)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[illuminate/pipeline

The Illuminate Pipeline package.

9346.6M213](/packages/illuminate-pipeline)[illuminate/pagination

The Illuminate Pagination package.

10532.5M862](/packages/illuminate-pagination)[mrmarchone/laravel-auto-crud

Laravel Auto CRUD helps you streamline development and save time.

28711.8k2](/packages/mrmarchone-laravel-auto-crud)[spatie/laravel-mix-preload

Add preload and prefetch links based your Mix manifest

169176.0k2](/packages/spatie-laravel-mix-preload)[interaction-design-foundation/laravel-geoip

Support for multiple Geographical Location services.

17221.0k3](/packages/interaction-design-foundation-laravel-geoip)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
