PHPackages                             metamorph/metamorph - 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. metamorph/metamorph

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

metamorph/metamorph
===================

Transformation library

v0.1.0(7y ago)2272MITPHPPHP &gt;=7.1

Since Aug 17Pushed 7y ago1 watchersCompare

[ Source](https://github.com/MetamorphPHP/metamorph)[ Packagist](https://packagist.org/packages/metamorph/metamorph)[ RSS](/packages/metamorph-metamorph/feed)WikiDiscussions master Synced 3d ago

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

Metamorph
=========

[](#metamorph)

Transform your data

[![CircleCI](https://camo.githubusercontent.com/859ce3eaee9392f85e1a67c10a8911888b357754b444ee8f739cf52396d4f980/68747470733a2f2f636972636c6563692e636f6d2f67682f4d6574616d6f7270685048502f6d6574616d6f7270682f747265652f6d61737465722e7376673f7374796c653d737667)](https://circleci.com/gh/MetamorphPHP/metamorph/tree/master)

Install
-------

[](#install)

```
composer require metamorph/metamorph

```

Usage
-----

[](#usage)

```
$transformer = new Metamorph($config);

$resource = new Collection($incomingData);

$transformedData = $transformer->transform($resource)->as('user')->from('object')->to('response');
```

Getting Started
---------------

[](#getting-started)

You will use a YAML file so set up the configuration of the transformers. The configuration should be in array with the key `metamorph` and an array of config values. The incoming data can be transformed into an array or into an object.

Your default objects are set in the `objects` value. It is assumed the default is an object and has an associated class. First, set a reference name for the object, in this case `user`.To configure the class for the object, use a `class` value. The name of the class is NOT fully qualified. That gets handled elsewhere in the configuration. You configuration would look like this so far

```
$config = [
  'metamorph' =>
    'objects' => [
      'user' => [
        'class' => 'TestUser',
      ],
    ],
  ],
];
```

You'll need to identify the properties in the class, do that with a `properties` key and an associative array of properties. The name of the property should be the key and the attributes of the property are contained in that key. You can have a `scalar` value, like a `string` or `int`. That would be configured like this

```
$config = [
  'metamorph' => [
    'objects' => [
      'user' => [
        'class' => 'TestUser',
        'properties' => [
          'allowed' => [
            'scalar' => 'bool',
          ],
        ],
      ],
    ],
  ],
];
```

The property could be the value of a configured object, like an email. The config would look like this

```
$config = [
  'metamorph' => [
    'objects' => [
      'user' => [
        'class' => 'User',
        'properties' => [
          'allowed' => [
            'scalar' => 'bool',
          ],
          'email' => [
            'object' => 'email',
          ],
        ],
      ],
      'email' => [
        'class' => 'Email',
        'properties' => [
          'label' => [
            'scalar' => 'string',
          ],
          'value' => [
            'scalar' => 'string',
          ],
        ],
      ],
    ],
  ],
];
```

If you wanted to have more than one email address in the property, you could set `isCollection` to `true`. You configuration would now look like this.

```
$config = [
  'metamorph' => [
    'objects' => [
      'user' => [
        'class' => 'User',
        'properties' => [
          'allowed' => [
            'scalar' => 'bool',
          ],
          'email' => [
            'isCollection' => true,
            'object' => 'email',
          ],
        ],
      ],
      'email' => [
        'class' => 'Email',
        'properties' => [
          'label' => [
            'scalar' => 'string',
          ],
          'value' => [
            'scalar' => 'string',
          ],
        ],
      ],
    ],
  ],
];
```

The `email` property of the `User` class will now be treated like an array in the generated transformer.

The final type that a property could be is a fully qualified class. An example might be using a uuid for the id of the class. You would have a `class` key with the fully qualified class name one of the property attributes.

```
$config = [
  'metamorph' => [
    'objects' => [
      'user' => [
        'class' => 'User',
        'properties' => [
          'allowed' => [
            'scalar' => 'bool',
          ],
          'email' => [
            'isCollection' => true,
            'object' => 'email',
          ],
          'id'=> [
              'class' => \Ramsey\Uuid\Uuid::class,
          ],
        ],
      ],
      'email' => [
        'class' => 'Email',
        'properties' => [
          'label' => [
            'scalar' => 'string',
          ],
          'value' => [
            'scalar' => 'string',
          ],
        ],
      ],
    ],
  ],
];
```

You'll want to transform the data from and to different sources. You might have the data come in an http request as JSON that is decoded to an array. The client side may have different property name. For example, the client side property is called `is_allowed` instead of `allowed`. We are going to need to have configuration for transformation. We do that with a `transformer` key and an array of usages. For this case, we'll call the useage `request`. Our config would look like this

```
$config = [
  'metamorph' => [
    'objects' => [ ... ],
    'transformers' => [
      'request' => [
        'class' => null,
        'properties' => [
          'allowed' => [
            'name' => 'is_allowed'
          ],
        ],
      ],
    ],
  ],
];
```

Notice the class type was set to `null`. This means the request is expected to be an array.

You may need to have the proprety value transformed from one type to another. These types be `class`es, `object`s, or `scalar`s, like with the object configuration. An example of this might be the uuid being a string an not an object when it is in the request.

```
$config = [
  'metamorph' => [
    'objects' => [ ... ],
    'transformers' => [
      'request' => [
        'class' => null,
        'properties' => [
          'allowed' => [
            'name' => 'is_allowed'
          ],
          'id' => [
            'scalar' => 'string'
          ],
        ],
      ],
    ],
  ],
];
```

A value can be transformed in different ways, depending on the the direction the transformation is happening. For example, for a date, you might be willing to transform from any format coming in, but only an ISO8601 on the way out. You would configure that like this.

```
$config = [
  'metamorph' => [
    'objects' => [ ... ],
    'transformers' => [
      'request' => [
        'class' => null,
        'properties' => [
          'allowed' => [
            'name' => 'is_allowed'
          ],
          'birthday' => [
            '_from' => ['format' => 'inclusiveDateTime'],
            '_to' => ['format' => 'Iso8601'],
          ],
          'id' => [
            'scalar' => 'string'
          ],
        ],
      ],
    ],
  ],
];
```

But wait! There is no birthday in the object! That's ok, when the `request` is being tranformed to the `object`, the data will just be ignored. Any properties that have the same property name and data type can be ignored in the transformer configuration. If there are any properties in the object that should not be included in the tranformed usage, you can simply `exclude` them.

```
$config = [
  'metamorph' => [
    'objects' => [ ... ],
    'transformers' => [
      'request' => [
        'class' => null,
        'exclude' => [
          'email',
        ],
        'properties' => [
          'allowed' => [
            'name' => 'is_allowed'
          ],
          'birthday' => [
            '_from' => ['format' => 'inclusiveDateTime'],
            '_to' => ['format' => 'Iso8601'],
          ],
          'id' => [
            'scalar' => 'string'
          ],
        ],
      ],
    ],
  ],
];
```

Configure for Generation
------------------------

[](#configure-for-generation)

```
$config = [
  'metamorph' => [
    'objects' => [ ... ],
    'transformers' => [ ... ],
    'config'       => [
      'entities' => [
        '_path'      => __DIR__.'/../../_support/Fixture',
        '_namespace' => 'Tests\Fixture',
      ],
      'transformers' => [
        '_path'      => __DIR__.'/../../_support/Fixture/Transformer',
        '_namespace' => 'Tests\Fixture\Transformer',
        'address'    => [
          '_path'      => __DIR__.'/../../_support/Fixture/Transformer/User',
          '_namespace' => 'Tests\Fixture\Transformer\User',
        ],
      ],
      'transformations' => [
        __DIR__.'/Transformation',
      ],
      'usage' => [
        'object' => [
          'array' => [
            'user',
          ],
        ],
        'array' => [
          'object' => [
            'user',
          ],
        ],
      ],
    ],
  ],
];
```

`transformations` are directories to classes that will covert between data types and formats. `usages` are the ways data can be transformed. It is configured by setting the usage as the key and the value is an array of usages it can get transformed to. In each of the usages is the object label of what is tobe transformed.

Generate the Transformers
-------------------------

[](#generate-the-transformers)

```
morph generate

```

This will read from `resources/metamorph` by default. If you want to read from a different directory then you can set the path in the command

```
morph generate --path=/home/path/config

```

Documentation to write still ...
--------------------------------

[](#documentation-to-write-still-)

- Transformations
- configuration for classes, target namespace and location for transformers, location of transformations, usage configuration

To Do:
------

[](#to-do)

- allow for specified properties to be returned, like happens in a GraphQL query.

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 60% 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

2827d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/bd5a2c6deedf2f52379d21fa55c9f5c6d0999b0ac1ca2ca2f33293e229107bfe?d=identicon)[iampersistent](/maintainers/iampersistent)

![](https://www.gravatar.com/avatar/4b19c15321a1a85897966d14deba2e5c35961af9eb2fc89760ca5f663ae71c6c?d=identicon)[timzagelow](/maintainers/timzagelow)

---

Top Contributors

[![timzagelow](https://avatars.githubusercontent.com/u/5422627?v=4)](https://github.com/timzagelow "timzagelow (3 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (2 commits)")

---

Tags

transformer

###  Code Quality

TestsCodeception

### Embed Badge

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

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

###  Alternatives

[symfony/maker-bundle

Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.

3.4k111.1M568](/packages/symfony-maker-bundle)[yzen.dev/plain-to-class

Class-transformer to transform your dataset into a structured object

16293.9k6](/packages/yzendev-plain-to-class)[ondrejmirtes/better-reflection

Better Reflection - an improved code reflection API

136.2M4](/packages/ondrejmirtes-better-reflection)[jasonlam604/stringizer

Stringizer is a PHP string manipulation library with support for method chaining and multibyte handling

35110.5k1](/packages/jasonlam604-stringizer)[selective/transformer

A strictly typed array transformer with dot-access, fluent interface and filters.

3817.8k1](/packages/selective-transformer)[deefour/transformer

Transform raw input data into consistent, immutable PHP objects

1251.0k2](/packages/deefour-transformer)

PHPackages © 2026

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