PHPackages                             cmath10/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. cmath10/mapper

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

cmath10/mapper
==============

Mapping library

1.0.2(4y ago)0151MITPHPPHP &gt;=7.4

Since Apr 16Pushed 4y ago1 watchersCompare

[ Source](https://github.com/cmath10/mapper)[ Packagist](https://packagist.org/packages/cmath10/mapper)[ Docs](https://github.com/cmath10/mapper)[ RSS](/packages/cmath10-mapper/feed)WikiDiscussions main Synced 6d ago

READMEChangelogDependencies (4)Versions (6)Used By (1)

Mapper
======

[](#mapper)

The library provides a utility for converting objects to each other (and arrays to objects) and transferring data between them by reusable map.

Basic example:

```
class ArticleInput
{
    public $title;

    public $text;

    public $author;
}

class Article
{
    public $title;

    public $text;

    public $author;

    public function __construct(?string $title = null)
    {
        $this->title = $title;
    }
}

$input = new ArticleInput();
$input->title = 'title';
$input->text = 'text';

$article1 = new Article();

$mapper = new cmath10\Mapper\Mapper();
$mapper->create(ArticleInput::class, Article::class);

$mapper->map($input, $article1);

// ($article1->title === 'title') === true
// ($article1->text === 'text') === true

$article2 = $mapper->map($input, Article::class)

// ($article2 instanceof Article) === true
// ($article2->title === 'title') === true
// ($article2->text === 'text') === true
```

How it works
------------

[](#how-it-works)

The main term of the library is a map. It is an object which is containing information about how to extract values from the source and inject them into a destination object. Values can be processed before injection (to get an opportunity for sanitization and nested mapping).

Map includes:

- field accessors — objects are responsible for value extraction; by default, it is used `symfony/property-access`for that purpose, but there are other options, like using callbacks or `symfony/expression-language` and presets (if the extracted value is null), also there is an interface for custom accessors;
- field filters — objects are responsible for value processing; by default, there are no filters for extracted value; you can use callbacks and mapping filters for nested mapping.

By default, a map creates a set of accessors based on a class properties list, so a field from a source will be mapped on a field of a destination with the same name. You can change this behavior for specific fields if needed.

All maps must be registered in a mapper instance before using. When you call the mapper method `map` it seeks the correct map for a given source and destination, then it uses accessors to extract values, filters to process them, and, after that, injects values to a destination. If the destination is a class name, the mapper will try to create an instance of the given class, if the class constructor is public and all possible arguments are optional.

Installation
------------

[](#installation)

```
composer require cmath10/mapper
```

API
---

[](#api)

`cmath10\Mapper\MapperInterface` — interface for mappers:

- `create(string $sourceType, string $destinationType)` — creates, registers and returns default map for two classes;
- `register(MapInterface $map)` — registers a custom map in the mapper;
- `map($source, $destination)` — performs mapping from a source to a destination object or class.

`cmath10\mapper\MapInterface` — interface for maps:

- `getSourceType()` — returns name of source type; used to find the correct map;
- `getDestinationType()` — returns name of destination type; used to find the correct map;
- `getFieldAccessors()` — returns all fields accessors;
- `getFieldFilters()` — returns all fields filters;
- `getOverwriteIfSet()` — returns boolean flag; if true, destination member will be overwritten even if its value is not null;
- `getSkipNull()` — returns boolean flag; if true, the mapper will not push null source member's value;
- `route(string $destinationMember, string $sourceMember)` — sets mapping of destination route to source route; fluent;
- `forMember(string $destinationMember, AccessorInterface $fieldMapper)` — sets custom accessor for field; fluent;
- `filter(string $destinationMember, FilterInterface $fieldFilter)` — sets a custom filter for value processing; fluent;
- `ignoreMember(string $destinationMember)` — excludes members from accounting, so they will not be filled; fluent.

`cmath10\mapper\FieldAccessor\AccessorInterface` — interface for accessors:

- `getValue($source)` — extracts value from a source.

`cmath10\mapper\FieldFilter\FitlerInterface` — interface for filters:

- `filter($value)` — processes the value.

`cmath10\Mapper\TypeFilterInterface` — interface for type filters is used to process type names. Useful for extracting class names from runtime generated classes like proxies in Doctrine. Used in default mapper which uses an array of type filters as a constructor parameter (to instantiate `cmath10\mapper\TypeGuesser` which is used to determine the correct map for supplied types in mapper's `map` method).

### Available maps

[](#available-maps)

#### AbstractMap

[](#abstractmap)

Basic class is used to create custom map classes, implements `MapperInterface`; provides following protected method:

- `setupDefaults` — creates a set of accessors based on a class properties list.

Usage example:

```
use cmath10\Mapper\AbstractMap;

class ArticleOutputMap extends AbstractMap
{
    public function __construct()
    {
        $this
            ->setupDefaults() // create default accessors set
            ->route('textNotMappedByDefault', 'text') // customize
        ;
    }

    public function getSourceType(): string
    {
        return Article::class;
    }

    public function getDestinationType(): string
    {
        return ArticleOutput::class;
    }
}
```

#### DefaultMap

[](#defaultmap)

Simple descendant of `AbstractMap`, just calls `setupDefaults` in its constructor; the mapper `create` method creates, registers and returns instance of this class.

### Available accessors

[](#available-accessors)

#### ClosureAccessor

[](#closureaccessor)

Uses callback to extract a value:

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldAccessor\ClosureAccessor;

$mapper = new Mapper();
$mapper
    ->create(Fixtures\Article::class, Fixtures\ArticleInput::class)
    ->forMember('author', new ClosureAccessor(fn (Fixtures\ArticleInput $a) => $a->author->name))
;
```

#### ExpressionAccessor

[](#expressionaccessor)

Uses `symfony/expression-language` to extract a value:

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldAccessor\ExpressionAccessor;

$mapper = new Mapper();
$mapper
    ->create(Fixtures\MagazineWithPrivateProperties::class, Fixtures\MagazineOutput::class)
    ->forMember('articles', new ExpressionAccessor('getArticles()'))
;
```

#### PresetAccessor

[](#presetaccessor)

Does not extract a value, just provides:

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldAccessor\PresetAccessor;

$mapper = new Mapper();
$mapper
    ->create(Fixtures\MagazineWithPrivateProperties::class, Fixtures\MagazineOutput::class)
    ->forMember('articles', new PresetAccessor([]))
;
```

#### PropertyPathAccessor

[](#propertypathaccessor)

Uses `symfony/property-access` to extract a value. This accessor is used by default. Calls like:

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldAccessor\PropertyPathAccessor;

$mapper = new Mapper();
$mapper
    ->create(Fixtures\MagazineWithPrivateProperties::class, Fixtures\MagazineOutput::class)
    ->forMember('articles', new PropertyPathAccessor('someFieldWithArticles'))
;
```

and

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldAccessor\PropertyPathAccessor;

$mapper = new Mapper();
$mapper
    ->create(Fixtures\MagazineWithPrivateProperties::class, Fixtures\MagazineOutput::class)
    ->route('articles', 'someFieldWithArticles')
;
```

are equivalent. Also, if the fields in a source and destination have the same name, and you use `setupDefaults`, you don't need to call `route` or `forMember` explicitly.

### Available filters

[](#available-filters)

#### ClosureFilter

[](#closurefilter)

Uses callback to process value:

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldFilter\ClosureFilter;

// For ArticleInput title='title' we will get Article title='[[title]]'
$mapper = new Mapper();
$mapper
    ->create(Fixtures\ArticleInput::class, Fixtures\Article::class)
    ->filter('title', new ClosureFilter(static fn ($title) => '[[' . $title . ']]'))
;
```

#### IfNullFilter

[](#ifnullfilter)

Replaces the value if it is null:

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldFilter\IfNullFilter;

// For ArticleInput title=null we will get Article title='defaultTitle'
$mapper = new Mapper();
$mapper
    ->create(Fixtures\ArticleInput::class, Fixtures\Article::class)
    ->filter('title', new IfNullFilter('defaultTitle'))
;
```

#### AbstractMappingFilter

[](#abstractmappingfilter)

Basic class for filters that can use mapper. Requires class name in the constructor. Used for nested mapping.

#### ObjectMappingFilter

[](#objectmappingfilter)

Descendant of `AbstractMappingFilter`, uses class name and mapper to make an object from a source member:

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldFilter\ObjectMappingFilter;

$mapper = new Mapper();
$mapper->create(Fixtures\AuthorInput::class, Fixtures\Author::class);
$mapper
    ->create(Fixtures\ArticleInput::class, Fixtures\Article::class)
    ->route('author', 'author')
    ->filter('author', new ObjectMappingFilter(Fixtures\Author::class))
;
```

#### ObjectArrayMappingFilter

[](#objectarraymappingfilter)

Descendant of `AbstractMappingFilter`, uses class name and mapper to make an array of objects from a source member, if the source member's value is array (returns an empty array instead):

```
use cmath10\Mapper\Mapper;
use cmath10\Mapper\FieldFilter\ObjectArrayMappingFilter;

$mapper = new Mapper();
$mapper->create(Fixtures\Article::class, Fixtures\ArticleOutput::class);
$mapper
    ->create(Fixtures\Magazine::class, Fixtures\MagazineOutput::class)
    ->route('articles', 'articles')
    ->filter('articles', new ObjectArrayMappingFilter(Fixtures\ArticleOutput::class))
;
```

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity56

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

Every ~194 days

Total

3

Last Release

1470d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/16908954?v=4)[Kirill Zaytsev](/maintainers/cmath10)[@cmath10](https://github.com/cmath10)

---

Top Contributors

[![cmath10](https://avatars.githubusercontent.com/u/16908954?v=4)](https://github.com/cmath10 "cmath10 (19 commits)")

---

Tags

mapperautomapper

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

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

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

###  Alternatives

[winzou/state-machine

A very lightweight yet powerful PHP state machine

52113.7M18](/packages/winzou-state-machine)[cuyz/valinor

Dependency free PHP library that helps to map any input into a strongly-typed structure.

1.5k9.2M108](/packages/cuyz-valinor)[mark-gerarts/auto-mapper-plus

An AutoMapper for PHP

5623.2M21](/packages/mark-gerarts-auto-mapper-plus)[eventsauce/object-hydrator

Converts structured data into strict objects.

3322.3M20](/packages/eventsauce-object-hydrator)[solspace/craft-freeform

The most flexible and user-friendly form building plugin!

52664.9k12](/packages/solspace-craft-freeform)[acelot/automapper

Powerful declarative data mapper for PHP 8

694.2k1](/packages/acelot-automapper)

PHPackages © 2026

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