doctrine-json-odm icon indicating copy to clipboard operation
doctrine-json-odm copied to clipboard

Use Attribute to set type_map instead of config

Open gabplch opened this issue 10 months ago • 3 comments

In new Symfony version a lot of configs are migrationg to attributes. What about to make smae this in this bundle?

E.g. wa have POPO model FooBar:

#[TypeMap('foo_bar')]
class FooBar {
     private string $someProperty;
}

gabplch avatar Apr 25 '24 10:04 gabplch

If this case is ok for you, I can make PR, when will have some free time

gabplch avatar Apr 25 '24 10:04 gabplch

Good idea. PR welcome!

dunglas avatar Apr 25 '24 11:04 dunglas

Hi :)

I implemented basic support for attributes in one of my projects, with a custom compiler pass.

In my implementation I ignore the type_map and only use my own attribute, but for the general case I think it's best to merge these two. It could be useful, when some of the classes are not editable (e.g. because they are from a library,..)

Do you have any thoughts on that?

Maybe just like this:

$typeMap = array_merge($config['type_map'] ?? [], $this->loadTypeMapFromAttributes($container));

if ($typeMap) {
    $container->getDefinition('dunglas_doctrine_json_odm.type_mapper')->addArgument($config['type_map']);
} else {
    $container->removeDefinition('dunglas_doctrine_json_odm.type_mapper');
}

The attribute could be just a simple one with only one property called type, and for the loading:

private function loadTypeMapFromAttributes(ContainerBuilder $container): array
{
    $typeMap = [];

    foreach ($container->getDefinitions() as $id => $definition) {
        $class = $container->getReflectionClass($definition->getClass(), false);

        if ($class) {
            $typeMapAttr = $class->getAttributes(TypeMap::class);
            $typeMapAttrCount = count($typeMapAttr);

            if ($typeMapAttrCount === 1) {
                $typeMapAttr = $typeMapAttr[0]->newInstance();
                $typeMap[$typeMapAttr->name] = $definition->getClass();
            }
            elseif ($typeMapAttrCount > 1) {
                 throw new \Exception('only one TypeMap-attribute is allowed on class ' . $definition->getClass());
            }
        }
    }

    return $typeMap;
}

Greetings :)

crazy-weasel avatar Sep 28 '24 12:09 crazy-weasel