Symfony2 - Como obter dinamicamente o Entity Manager de uma entidade Doctrine
Estamos construindo uma plataforma de criação de sites e CMS e com muitos sites diferentes de fornecedores e clientes, portanto, existem várias entidades do tipo de conteúdo, editadas por controladores genéricos e serviços auxiliares que não necessariamente (facilmente) sabem o que o gerente de entidade é para uma determinada entidade.
NOTA: Temos vários entityManagers para separar o acesso a diferentes bancos de dados, por exemplo, Global, Faturamento, Local, etc
Existem muitos casos em que precisamos detectar qual é o EntityManager da entidade. Por exemplo, temos um MediaHelper que associa dinamicamente a mídia de um banco de dados a campos correspondentes na entidade (isso não funciona com associações porque a Mídia precisa se conectar com literalmente qualquer entidade e você não pode ter esse tipo de associação dinâmica e não queremos cem associações diferentes).
A mídia está em um pacote gerenciado pelo EntityManager 'Local'. Mas a entidade pode estar em um EntityManager 'Global' (você não pode presumir que esteja no mesmo gerenciador de entidades). Portanto, precisamos detectar e persistir o gerente de entidade certo para a entidade certa.
Então, como você recomenda detectar dinamicamente o entityManager de uma entidade?
Método personalizado originalNOTA: a resposta aceita é uma solução muito melhor. Este é apenas aqui para fins de arquivo.
Aqui está uma solução simples que funciona. Mas não sei o suficiente sobre o Symfony e o Doctrine para saber se é uma má ideia? Alguém mais sabe? Caso contrário, não sei por que isso não estaria no núcleo, como um Utilitário de Doutrina.
Criei um serviço EntityHelper que injeta o serviço Doctrine nele:
gutensite_cms.entity_helper:
class: Gutensite\CmsBundle\Service\EntityHelper
arguments:
- "@doctrine"
Então, no assistente de entidade, há uma função simples para obter o Gerenciador de Entidades para uma entidade (o config.yml já registra os pacotes configuráveis para os gerenciadores de entidades):
/**
* Automagically find the entityManager for an entity.
* @param $entity
* @return mixed
*/
public function getManagerForEntity($entity) {
$className = \Doctrine\Common\Util\ClassUtils::getRealClass(get_class($entity));
foreach (array_keys($this->doctrine->getManagers()) as $name) {
if(in_array($className, $this->doctrine->getManager($name)->getConfiguration()->getMetadataDriverImpl()->getAllClassNames())) return $em;
}
}
NOTA:Registro da doutrina # getAliasNamespace já faz algo quase idêntico a esse loop foreach, modifiquei a ideia para retornar o gerente da entidade em vez do namespace, por exemplo
public function getAliasNamespace($alias) {
foreach (array_keys($this->getManagers()) as $name) {
try {
return $this->getManager($name)->getConfiguration()->getEntityNamespace($alias);
} catch (ORMException $e) {
}
}
throw ORMException::unknownEntityNamespace($alias);
}
Atualização 21/10/15: Código de detecção de entidade atualizado por sugestão da @ Cerad.