PHPackages                             liip/metadata-parser - 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. liip/metadata-parser

ActiveLibrary

liip/metadata-parser
====================

Parser for metadata

2.0.0(5mo ago)17367.7k↓37%8[1 PRs](https://github.com/liip/metadata-parser/pulls)1MITPHPPHP ^8.0CI passing

Since Feb 12Pushed 5mo ago15 watchersCompare

[ Source](https://github.com/liip/metadata-parser)[ Packagist](https://packagist.org/packages/liip/metadata-parser)[ RSS](/packages/liip-metadata-parser/feed)WikiDiscussions 2.x Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (16)Used By (1)

Liip Metadata Parser
====================

[](#liip-metadata-parser)

**This project is Open Sourced based on work that we did initially as closed source at Liip, it may be lacking some documentation. If there is anything that you need or have questions about we would love to see you open an issue! :)**

This is a parser for building model metadata from PHP classes. The metadata model can then be used to generate code or configuration. For example a serializer or ElasticSearch schema for types.

The metadata is geared toward this use case. PHP level constructs that represent the same information are grouped together: Methods for virtual properties and fields that have the same serialized name, but are valid in different versions.

This extensible parser can process PHP code and annotations or other metadata. You could write your own parsers, but this library comes with support for:

- Reflection
- PhpDoc
- JMSSerializer annotations

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

[](#contributing)

If you want to contribute to the project (awesome!!), please read the [Contributing Guidelines](https://github.com/liip/metadata-parser/blob/master/CONTRIBUTING.md)and adhere to our [Code Of Conduct](https://github.com/liip/metadata-parser/blob/master/CODE_OF_CONDUCT.md)

Where do I go for help?
-----------------------

[](#where-do-i-go-for-help)

If you need, open an issue.

Setup
-----

[](#setup)

```
use Doctrine\Common\Annotations\AnnotationReader;
use Liip\MetadataParser\Builder;
use Liip\MetadataParser\Parser;
use Liip\MetadataParser\RecursionChecker;
use Liip\MetadataParser\ModelParser\JMSParser;
use Liip\MetadataParser\ModelParser\LiipMetadataAnnotationParser;
use Liip\MetadataParser\ModelParser\PhpDocParser;
use Liip\MetadataParser\ModelParser\ReflectionParser;
use Liip\MetadataParser\ModelParser\VisibilityAwarePropertyAccessGuesser;

$parser = new Parser(
    new ReflectionParser(),
    new PhpDocParser(),
    new JMSParser(new AnnotationReader()),
    new VisibilityAwarePropertyAccessGuesser(),
    new LiipMetadataAnnotationParser(new AnnotationReader()),
);

$recursionChecker = new RecursionChecker(new NullLogger());

$builder = new Builder($parser, $recursionChecker);
```

Usage
-----

[](#usage)

The `Builder::build` method is the main entry point to get a `ClassMetadata`object. The builder accepts an array of `Reducer` to select which property to use when there are several options. A reducer can lead to drop a property if none of the variants is acceptable. Multiple options for a single field mainly come from the `@SerializedName` and `@VirtualProperty` annotations of JMSSerializer:

- GroupReducer: Select the property based on whether it is in any of the specified groups;
- VersionReducer: Select the property based on whether it is included in the specified version;
- TakeBestReducer: Make sure that we end up with the property that has the same name as the serialized name, if we still have multiple options after the other reducers.

```
use Liip\MetadataParser\Reducer\GroupReducer;
use Liip\MetadataParser\Reducer\PreferredReducer;
use Liip\MetadataParser\Reducer\TakeBestReducer;
use Liip\MetadataParser\Reducer\VersionReducer;

$reducers = [
    new VersionReducer('2'),
    new GroupReducer(['api', 'detail']),
    new PreferredReducer(),
    new TakeBestReducer(),
];
$metadata = $builder->build(MyClass::class, $reducers);
```

The `ClassMetadata` provides all information on a class. Properties have a `PropertyType` to tell what kind of property they are. Properties that hold another class, are of the type `PropertyTypeClass` that has the method `getClassMetadata()` to get the metadata of the nested class. This structure is validated to not contain any infinite recursion.

### Property naming strategy

[](#property-naming-strategy)

By default, property names will be translated from a camelCased to a lower and snake\_cased name (e.g. `myProperty` becomes `my_property`). If you want to keep the property name as is, you can change the strategy to `identical` by passing the corresponding strategy to the parser.

```
use Liip\MetadataParser\Builder;
use Liip\MetadataParser\ModelParser\NamingStrategy\IdenticalPropertyNamingStrategy;

$identicalNamingStrategy = new IdenticalPropertyNamingStrategy();

$parser = new Parser(
    [
        // your parsers
    ],
    new IdenticalPropertyNamingStrategy()
);

$builder = new Builder($parser)
```

You can also create your own naming strategy by implementing the `Liip\MetadataParser\ModelParser\NamingStrategy\PropertyNamingStrategyInterface`

### Handling Edge Cases with @Preferred

[](#handling-edge-cases-with-preferred)

This library provides its own annotation in `Liip\MetadataParser\Annotation\Preferred`to specify which property to use in case there are several options. This can be useful for example when serializing models without specifying a version, when they use different virtual properties in different versions.

```
use JMS\Serializer\Annotation as JMS;
use Liip\MetadataParser\Annotation as Liip;

class Product
{
    /**
     * @JMS\Since("2")
     * @JMS\Type("string")
     */
    public $name;

    /**
     * @JMS\Until("1")
     * @JMS\SerializedName("name")
     * @JMS\Type("string")
     * @Liip\Preferred
     */
    public $legacyName;
}
```

### Expected Recursion: Working with Flawed Models

[](#expected-recursion-working-with-flawed-models)

#### JMS annotation

[](#jms-annotation)

If you are using JMS annotations, you can add the `MaxDepth` annotation to properties that might be recursive.

The following example will tell the metadata parser that the recursion is expected up to a maximum depth of `3`.

```
use JMS\Serializer\Annotation as JMS;

class RecursionModel
{
    /**
     * @JMS\MaxDepth(3)
     * @JMS\Type("RecursionModel")
     */
    public $recursion;
}
```

#### Pure PHP

[](#pure-php)

The RecursionChecker accepts a second parameter to specify places where to break recursion. This is useful if your model tree looks like it has recursions but actually does not have them. JMSSerializer always acts on the actual data and therefore does not notice a recursion as long as it is not infinite.

For example, lets say you have a `Product` that has a field `variants` which is again list of `Product`. Those variant products use the same class and therefore have the `variants` field. However, in real data a variant never contains further variants. To avoid a recursion exception for this example, you would specify:

```
$expectedRecursions = [
    ['variants', 'variants'],
];
$recursionChecker = new RecursionChecker(new NullLogger(), $expectedRecursions);
```

With this configuration, the `ClassMetadata` found in the property type for the variants property of the final model will have no field `variants`, so that code working on the metadata does not need to worry about infinite recursion.

Extending the metadata parser
-----------------------------

[](#extending-the-metadata-parser)

This library comes with a couple of parsers, but you can write your own to handle custom information specific to your project. Use the `PropertyVariationMetadata::setCustomInformation` method to add custom data, and use `PropertyMetadata::getCustomInformation` to read it in your metadata consumers.

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance70

Regular maintenance activity

Popularity46

Moderate usage in the ecosystem

Community30

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 58.2% 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 ~165 days

Recently: every ~189 days

Total

16

Last Release

168d ago

Major Versions

0.6.1 → 1.0.02023-02-13

1.x-dev → 2.0.02025-12-01

PHP version history (4 changes)0.1PHP ^7.1

0.3.0PHP ^7.2 || ^8.0

1.1.0PHP ^7.4 || ^8.0

2.0.0PHP ^8.0

### Community

Maintainers

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

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

![](https://avatars.githubusercontent.com/u/76576?v=4)[David Buchmann](/maintainers/dbu)[@dbu](https://github.com/dbu)

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

![](https://www.gravatar.com/avatar/29288e00799aeecc129c437fe166003f4dd598637cef23b050eae6806b0b0bb0?d=identicon)[mjanser](/maintainers/mjanser)

![](https://www.gravatar.com/avatar/3c4c0e15d3d7112cdfd14cdf0ffc0544b956f5028b94dd2e5987978737539526?d=identicon)[bellisk](/maintainers/bellisk)

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

---

Top Contributors

[![dbu](https://avatars.githubusercontent.com/u/76576?v=4)](https://github.com/dbu "dbu (82 commits)")[![Spea](https://avatars.githubusercontent.com/u/495017?v=4)](https://github.com/Spea "Spea (33 commits)")[![ChristianRiesen](https://avatars.githubusercontent.com/u/1446701?v=4)](https://github.com/ChristianRiesen "ChristianRiesen (9 commits)")[![michellesanver](https://avatars.githubusercontent.com/u/570982?v=4)](https://github.com/michellesanver "michellesanver (6 commits)")[![brutal-factories](https://avatars.githubusercontent.com/u/143793262?v=4)](https://github.com/brutal-factories "brutal-factories (5 commits)")[![meyerbaptiste](https://avatars.githubusercontent.com/u/4034907?v=4)](https://github.com/meyerbaptiste "meyerbaptiste (1 commits)")[![mjanser](https://avatars.githubusercontent.com/u/1826722?v=4)](https://github.com/mjanser "mjanser (1 commits)")[![Neur0toxine](https://avatars.githubusercontent.com/u/24733820?v=4)](https://github.com/Neur0toxine "Neur0toxine (1 commits)")[![jlnfsslr](https://avatars.githubusercontent.com/u/87357150?v=4)](https://github.com/jlnfsslr "jlnfsslr (1 commits)")[![thePanz](https://avatars.githubusercontent.com/u/226021?v=4)](https://github.com/thePanz "thePanz (1 commits)")[![Tobion](https://avatars.githubusercontent.com/u/610090?v=4)](https://github.com/Tobion "Tobion (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/liip-metadata-parser/health.svg)

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

###  Alternatives

[phpbench/phpbench

PHP Benchmarking Framework

2.0k13.0M627](/packages/phpbench-phpbench)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[neos/flow

Flow Application Framework

862.0M451](/packages/neos-flow)[neos/flow-development-collection

Flow packages in a joined repository for pull requests.

144179.3k3](/packages/neos-flow-development-collection)[api-platform/metadata

API Resource-oriented metadata attributes and factories

243.5M96](/packages/api-platform-metadata)[hostnet/entity-tracker-component

Provides an event when a Tracked entity changes

16158.1k4](/packages/hostnet-entity-tracker-component)

PHPackages © 2026

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