PHPackages                             it-bens/object-transformer - 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. it-bens/object-transformer

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

it-bens/object-transformer
==========================

Mediator that performs transformations between objects by using transformation strategies.

v0.2.0(4y ago)112611MITPHPPHP ^8.0

Since Sep 21Pushed 2y ago1 watchersCompare

[ Source](https://github.com/it-bens/object-transformer)[ Packagist](https://packagist.org/packages/it-bens/object-transformer)[ RSS](/packages/it-bens-object-transformer/feed)WikiDiscussions master Synced today

READMEChangelog (2)Dependencies (4)Versions (4)Used By (1)

The Object Transformer
======================

[](#the-object-transformer)

[![Maintenance Status](https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667)](https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667)[![Build Status](https://camo.githubusercontent.com/c4c0dc8bb0288523f4c225dfaa1e67fb83696bf6da913eb74ab128016b332960/68747470733a2f2f6170702e7472617669732d63692e636f6d2f69742d62656e732f6f626a6563742d7472616e73666f726d65722e7376673f6272616e63683d6d6173746572)](https://app.travis-ci.com/it-bens/object-transformer)[![Coverage Status](https://camo.githubusercontent.com/7bf58b217ac8bdd8a9bb01ef672dbcc83e7838c1acab4affc9f08698c0272bd2/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f69742d62656e732f6f626a6563742d7472616e73666f726d65722f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/it-bens/object-transformer?branch=master)

How to install the package?
---------------------------

[](#how-to-install-the-package)

The package can be installed via Composer:

```
composer require it-bens/object-transformer
```

It requires at least PHP 8, but no other extensions or packages.

How to use the Object Transformer?
----------------------------------

[](#how-to-use-the-object-transformer)

First, at least one implementation of the `TransformerInterface` has to be created.

```
use ITB\ObjectTransformer\TransformerInterface;

class OptimusPrime implements TransformerInterface
{
    public static function supportedTransformations(): array
    {
        return [['input' => MissionCity::class, 'output' => Ruins::class]];
    }

    public function transform(TransformationEnvelope $envelope, string $outputClassName): object
    {
        // This method performs the actual transformation and returns the resulting object.
    }
}

class Megatron implements TransformerInterface
{
    public static function supportedTransformations(): array
    {
        return [['input' => SamWitwicky::class, 'output' => Corpse::class]];
    }

    public function transform(TransformationEnvelope $envelope, string $outputClassName): object {...}
}
```

The input- and output class names are used to register the supported transformations in the `TransformationMediator`.

The `TransformationMediator` requires an iterable of `TransfromerInterface`-implementing objects (at least one).

```
use ITB\ObjectTransformer\TransformationMediator;

$mediator = new TransformationMediator(new \ArrayObject([new OptimusPrime(), new Megatron()]));
```

Because the `TransformerInterface` objects are processed at the first call of the `transform` method of the `TransformationMediator`, the `TranformationMediator` (or the `TransformationMediatorInterface`) can be passed as constructor argument to the transformer (otherwise, this could lead to endless circle calls).

After everything is prepared, the `transform` method can be used.

```
$object1 = new Object1('The hell am I doing here?');
$object2 = $mediator->transform($object1, Object2::class);

// Explicit envelope usage
$object2 = $mediator->transform(TransformationEnvelope::wrap($object1), Object2::class);
```

The `transform` method of the `TransformationMediator` can handle any object. If the passed object isn't a `TransformationEnvelope`, it will be wrapped with one. So if you don't want to use any stamps (see below), just pass the ordinary object. But be aware, that you will always receive a `TransformationEnvelope` in your implementations of `TransformerInterface?`.

What do you mean with "stamp"?
------------------------------

[](#what-do-you-mean-with-stamp)

The envelope and stamp system is inspired, but not identical to the system used by the Symfony messenger component. Every object that is passed to the `transform` method of the `TransformationMediator` is wrapped with an `TransformationEnvelope`(if it's not already one).

Like a real envelope, the `TransformationEnvelope` can carry stamps. Stamps have two tasks:

1. pass data to the `transform` method of the `TransformerInterface` implementation
2. provide data that can be used during processing in the `TransformationMediator`

All stamps have to implement the `TransformationStampInterface` and provide a priority.

The main difference to the Symfony messenger component is, that the envelope can only hold one stamp per type. If two or more stamps of the same type are passed to the envelope, a later stamp will overwrite an earlier one, if it's priority is higher.

### Looping data through the mediator

[](#looping-data-through-the-mediator)

To loop data through the mediator to the transformer, any custom stamp can be passed to the envelope. They won't be touched during processing and are accessible via the envelope:

```
public function transform(TransformationEnvelope $envelope, string $outputClassName): object
{
    $customStamp = $envelope->getStamp(CustomStampClass::class); // returns null if the envelope contains no such stamp
}
```

### Data processed by the mediator

[](#data-processed-by-the-mediator)

All implementations of the `TransformationStampInterface` provided by this package are used inside the mediator. After there usage they are removed from the envelope and are not accessible in the `TransformerInface` implementation.

#### InputClassStamp

[](#inputclassstamp)

Because of its internal data flow, the passed input object has to be of the exact same class that was defined as input in the `supportedTransformations` method of the factory.

This could lead to problems with packages like Doctrine. Doctrine creates proxy classes for managed entities, that can be used just like the Entity itself. However, the `TransformationMediator` would not find a matching transformer and throw an exception, because the exact class of the proxy object is not registered for transformation.

That's where the `InputClassStamp` comes into play. Let's define some objects first.

```
class Object1
{
    public $someString;
    public function __construct($someString) { $this->someString = $someString; }
}

class Object2
{
    public $letterCount;
    public function __construct($letterCount) { $this->letterCount = $letterCount; }
}

class Object3 extends Object1
{
}
```

The following lines would lead to an `UnsupportedInputOutputTypes` exception.

```
$object3 = new Object3('The hell am I doing here?');
$result = $mediator->tranform($object3, Object2::class);
```

With the `InputClassStamp` it's working.

```
use ITB\ObjectTransformer\TransformationMediator;

$envelope = new \ITB\ObjectTransformer\TransformationEnvelope(
    new Object3('The hell am I doing here?'),
    [new InputClassStamp(Object1::class)]
);
$result = $mediator->tranform($envelope, Object2::class);
```

Why does this package exist?
----------------------------

[](#why-does-this-package-exist)

A common pattern I stumbled across in my projects is to map data between different objects types like DTOs and Entities.

The mapping is often very simple: the value of the DTO (Data Transfer Object) property is the same as the property of the Entity (and vice versa). However, things get more complicated if value objects are used (which I strongly recommend). New objects has to be created and the few lines of code get more and more complex.

In my projects, this often lead to the creation of factory classes, that handle the object transformation and contain as little business logic as possible. But, as a class should only serve a single purpose, there can be a lot of such factories. When engineering more complex entities, the factories sometimes depend on each other. That makes the DI (Dependency Injection) or Singleton usage quite a mess.

That's where the object transformer comes into play: the mediator is sufficient to do all the transformations needed.

How does the Object Transformer work?
-------------------------------------

[](#how-does-the-object-transformer-work)

A factory or any other class that should be used by the `TransformationMediator`has to implement the `TransformerInterface`.

All classes that implement the interface (and are passed to the mediator) provide an array of supported transformations via the static `supportedTransformations` method. The array contains an array for every supported transformation. Every one of these inner arrays requires an `input` and an `ouput` key, which both represent existing classes.

When the `transform` method of the `TransformationMediator` is first called, it will populate it's internal transformer registry. For performance reasons every supported transformation is registered with it's input and output class. This way, the associations can be used to find a responsible transformer.

Contributing
------------

[](#contributing)

I am really happy that the software developer community loves Open Source, like I do! ♥

That's why I appreciate every issue that is opened (preferably constructive) and every pull request that provides other or even better code to this package.

You are all breathtaking!

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity12

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity47

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 ~7 days

Total

2

Last Release

1684d ago

PHP version history (2 changes)v0.1.0PHP &gt;=7.1.3

v0.2.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/94aa1cc7aa38ca9d3f6bb96541ff813027df1f0cf478b3c53c41385876503b2c?d=identicon)[SpiGAndromeda](/maintainers/SpiGAndromeda)

---

Top Contributors

[![SpiGAndromeda](https://avatars.githubusercontent.com/u/15141351?v=4)](https://github.com/SpiGAndromeda "SpiGAndromeda (13 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/it-bens-object-transformer/health.svg)

```
[![Health](https://phpackages.com/badges/it-bens-object-transformer/health.svg)](https://phpackages.com/packages/it-bens-object-transformer)
```

###  Alternatives

[cubear/finder

Finder is a Drupal 8 module to help users find services which meet their criteria

404.2k](/packages/cubear-finder)

PHPackages © 2026

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