承接 elaitech/data-mapper 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

elaitech/data-mapper

Composer 安装命令:

composer require elaitech/data-mapper

包简介

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

README 文档

README

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

🚀 Installation

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:

  • DataMapperInterfaceDataMapperService (binding)
  • ValueTransformer — singleton with 10 built-in transformers
  • FieldExtractor — singleton

🏗 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

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: 'int',
        ),
    ]),
);

$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

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

Extracts values from data using:

Pattern Example Description
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

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

Name Label Description Requires Format
none None Pass-through, no transformation
trim Trim Remove leading/trailing whitespace
upper Uppercase Convert to UPPERCASE
lower Lowercase Convert to lowercase
int Integer Cast to int (extracts digits from messy strings; falls back to default)
float Float Cast to float with precision control ✅ (decimals)
bool Boolean Cast to bool (handles "true", "1", "yes", etc.)
date Date Parse and reformat dates ✅ (date format)
array_first Array First Extract first element from array
array_join Array Join Join array elements with separator ✅ (separator)

🗺 Field Extraction

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

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

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

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

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

MappingConfigurationData

Input to the mapper:

Property Type Description
data array Array of rows to map
mappingRules DataCollection<MappingRuleData> Mapping rules to apply
headers ?array Column headers for indexed rows

MappingRuleData

A single field mapping rule:

Property Type Default Description
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

Output from the mapper:

Property Type Description
data array Successfully mapped rows
errors array Per-row error messages

📜 Contracts

DataMapperInterface

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

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

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

# From the root project
php artisan test

📦 Dependencies

Package Version Purpose
illuminate/support ^12.0 Laravel framework support
spatie/laravel-data ^4.19 Typed DTOs with auto-mapping

📄 License

MIT

elaitech/data-mapper 适用场景与选型建议

elaitech/data-mapper 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 12 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 02 月 16 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 elaitech/data-mapper 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 elaitech/data-mapper 我们能提供哪些服务?
定制开发 / 二次开发

基于 elaitech/data-mapper 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 12
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 29
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-16