Skip to content

Instantly share code, notes, and snippets.

@bcastellano
Last active May 1, 2016 16:58
Show Gist options
  • Save bcastellano/272eaf33bf75b02fe63e443c3f602c0e to your computer and use it in GitHub Desktop.
Save bcastellano/272eaf33bf75b02fe63e443c3f602c0e to your computer and use it in GitHub Desktop.
Inject Doctrine repositories to services with compiler pass in Symfony 2
<?php
namespace AppBundle;
use AppBundle\DependencyInjection\Compiler\InjectRepositoriesCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AppBundle extends Bundle
{
/**
* @param ContainerBuilder $container
*/
public function build(ContainerBuilder $container)
{
parent::build($container);
// add compiler pass
$container->addCompilerPass(new InjectRepositoriesCompilerPass());
}
}
<?php
namespace AppBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
class InjectRepositoriesCompilerPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
// find tagged services
$services = $container->findTaggedServiceIds('doctrine.repository');
// for each service tagged inject repositories
foreach ($services as $key => $tags) {
// get tagged service
$definition = $container->getDefinition($key);
foreach ($tags as $tag) {
// replace each argument specified by tag
$this->replaceArgument($container, $definition, $tag);
}
}
}
/**
* Replaces arguments by entity repositories
*
* @param ContainerBuilder $container
* @param Definition $definition
* @param array $tag
* - argument <int> Argument to replace position. Mandatory
* - entity_manager <string> Service name for entity manager to use. Optional
* - repository <string> Name for repository service. Optional
*/
protected function replaceArgument(ContainerBuilder $container, Definition $definition, array $tag)
{
// get object class as service argument
$entityClass = $definition->getArgument($tag['argument']);
// get entity manager service from tag or parameters
$emServiceName = (isset($tag['entity_manager']) ? $tag['entity_manager'] : $container->getParameter('default_entity_manager_service'));
if (isset($tag['repository'])) {
// if repository is setted, then create repository as service
$repositoryClass = $container->getParameter('default_repository_class');
// get repository to replace
$dmDefinition = (new Definition($repositoryClass, [$entityClass]))
->setFactory([
new Reference($emServiceName),
'getRepository'
]);
// create repository as service
$container->setDefinition($tag['repository'], $dmDefinition);
// get repository service reference
$replacedArgument = new Reference($tag['repository']);
} else {
// get repository to replace
$replacedArgument = (new Definition(null, [$entityClass]))
->setFactory([
new Reference($emServiceName),
'getRepository'
]);
}
$definition->replaceArgument($tag['argument'], $replacedArgument);
}
}
parameters:
# mandatory parameter for doctrine entity manager
default_entity_manager_service: doctrine.orm.default_entity_manager
# optional parameter to create repositories as shared services
default_repository_class: Doctrine\ORM\EntityRepository
services:
# example 1
app_bundle.user.manager:
class: AppBundle\Model\Manager\UserManager
arguments: ["AppBundle:User"]
tags:
- { name: doctrine.repository, argument: 0 }
# example 2
app_bundle.post.manager:
class: AppBundle\Model\Manager\PostManager
arguments: ["AppBundle:Post"]
tags:
- { name: doctrine.repository, argument: 0, entity_manager: doctrine.orm.default_entity_manager, repository: app_bundle.post.repository }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment