zolex/vom

Versatile Object Mapper. Map arbitrary data to strictly typed models using PHP attributes.

Maintainers

Package info

github.com/zolex/vom

Type:symfony-bundle

pkg:composer/zolex/vom

Statistics

Installs: 137 576

Dependents: 0

Suggesters: 0

Stars: 19

Open Issues: 0

2.2.1 2026-03-14 14:48 UTC

README

Release Version Integration Code Coverage License Downloads

VOM

PHP Symfony Laravel

The Versatile Object Mapper - or in short VOM - is a PHP library to transform any data structure into strictly typed models (and back) by adding PHP 8 attributes. It extends symfony/serializer functionality and is heavily inspired by doctrine and API-Platform, so that advanced mappings can simply be defined on the model classes instead of writing normalizer decorators.

Installation

VOM is available on packagist. To install, simply require it via composer.

composer require zolex/vom ^2.0

Quickstart

To give you a basic idea of what VOM does, here is a first short example.

Given, your application receives the following array of values from somewhere.

$data = [
    'firstname' => 'Jane',
    'surname' => 'Doe',
    'street' => 'Samplestreet 123',
    'city' => 'Worsthausen',
    'zip' => '12345',
    'country_name' => 'United Kingdom',
    'email_address' => 'jane.doe@mailprovider.net',
    'phone' => '0123456789'
];

Usually you would write some code that creates the model instances, sets their properties and nests them properly. In very simple scenarios, writing the transformation logic as code might be a good choice, but it can be a pain when it comes to very huge models, the input data structures and/or application models change while still in development, or if you want to reuse the transformation logic in other projects too, because it receives the same inputs and/or uses the same models.

How it works using VOM

Instead of writing business logic that feeds your models, with VOM you simply configure the models using PHP attributes.

use Zolex\VOM\Mapping as VOM;

#[VOM\Model]
class Person
{
    #[VOM\Property]
    public string $firstname;
    
    #[VOM\Property('[surname]')]
    public string $lastname;
    
    #[VOM\Property(accessor: false)]
    public Address $address;
    
    #[VOM\Property(accessor: false)]
    public Contact $contact;
}

#[VOM\Model]
class Address
{
    #[VOM\Property]
    public string $street;
    
    #[VOM\Property('[zip]')]
    public string $zipCode;
    
    #[VOM\Property]
    public string $city;
    
    #[VOM\Property('[country_name]')]
    public string $country; 
}

#[VOM\Model]
class Contact
{
    #[VOM\Property('[email_address]')]
    public string $email;
    
    #[VOM\Property]
    public string $phone;
}

To create instances of your models, you simply pass the data to the denormalize() method.

$person = $objectMapper->denormalize($data, Person::class);

You may have noticed, that some property attributes have arguments while others don't. For all details on that, head to the full documentation.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributors

zolex
Andreas Linden
zolex
Javier Caballero

Special thanks

To Blackfire.io for supporting this project with a free license. Their tools help to identify optimization opportunities and provide valuable insights into the current performance characteristics of VOM.

Blackfire

Performance comparison between cached and uncached VOM metadata across 1000 iterations of denormalizing the same model. See tests/Profiling.

Alternatives

There are many Mapping/Transformation/Hydration libraries out there. In case you don't want to rely on symfony/serializer, symfony/proerty-access, symfony/type-info and phpdocumentor/reflection-docblock which VOM depends on, here are some alternative packages that cover the same topic with quite different approaches and features.