Doctrine Simple Mapping and Repository Compiler Pass

Recently I stumble upon some doctrine repository definition situation where there were many definitions of custom doctrine repositories. Instead of having a long list over and over of a custom doctrine service definition I started to look at simpler ways this can be just done and let that adapt within a compiler pass and be customized further down the road as much specific to the application as possible.

I checked out https://github.com/mmoreram/SimpleDoctrineMapping and even though this package seems to be interesting to simplify the auto-mapping in some way I wanted to really have a way to do the simplification not for the mapping of the entities but for the custom repository service definitions. One good thing about this library is that is not a bundle! yey!

So I ended up with just passing an array of parameters, with keys being the model classes, and the values being the repository fqcn’s.

<?php
 
namespace Vendor\Package\DependencyInjection\Compiler;
 
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
 
class CustomRepositoryPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getParameter('repositories') as $model => $class) {
            $definition = new Definition();
            $definition
                ->setClass($class)
                ->setArguments([$model])
                ->setFactoryMethod('getRepository')
                ->setFactoryService('doctrine')
                ->setPublic(true)
                ->setLazy(true)
            ;
 
            $container->setDefinition(
                'vendor.repository.'.$this->slug($class),
                $definition
            );
        }
    }
 
    private function slug($fqcn)
    {
        $fqcn = str_replace('Repository', '', $fqcn);
        $names = explode('\\', $fqcn);
        $string = end($names);
        $string = preg_replace('/([A-Z])/', '_$1', $string);
 
        return strtolower(substr($string,1));
    }
}

This as a first approach is simple and straight to the point. Now my 100’s of lines on service definitions for custom repositories were downed to just specifying the key value pairs as parameters:

parameters:
    repositories:
        Vendor\Package\Model\Action: Vendor\Package\Repository\ActionRepository
        Vendor\Package\Model\Tenant: Vendor\Package\Repository\TenantRepository
        // ...

This compiler pass can be used as i have shown in previous posts without the need of a bundle fortunately! And it can be further taylor to meet the domain needs of your domain packages.

Although in early stage I just wanted to put it out so it could benefit someone with the same problem. Take it just as an initial idea and then improve upon it like I am doing in other projects.

Encouragements, thanks for reading. Appreciated!

Leave a Reply

Your email address will not be published. Required fields are marked *