Symfony 2.8: Doctrine getManagerForClass () does not return the correct Entity Manager

tl; dr How does a method getManagerForClass()

find out which object manager is the correct one for a particular class?

I created a generic controller that should be able to handle basic actions for different objects. I also have connections to two different databases, so I am using two entity managers.

In my controller, I'm trying to use Doctrine's getManagerForClass () method to find which manager to use for each class, as described in this blog post and this SO answer .

But the method doesn't seem to distinguish between my two entity managers and just returns the first one in the config.

My controller actions start like this:

public function indexAction($namespace, $entityName)
{
    $classFullName = "AppBundle:$namespace\\$entityName";
    $em = $this->getDoctrine()->getManagerForClass($classFullName);

      

This is my Doctrine config:

dbal:
    default_connection: postgres
    connections:
        postgres:
            driver:   pdo_pgsql
            host:     "%database_host%"
            port:     "%database_port%"
            dbname:   "%database_name%"
            user:     "%database_user%"
            password: "%database_password%"
            charset:  UTF8

        oracle:
            driver:   oci8
            host:     "%oracle_host%"
            port:     "%oracle_port%"
            dbname:   "%oracle_name%"
            user:     "%oracle_user%"
            password: "%oracle_password%"
            charset:  UTF8

orm:
    auto_generate_proxy_classes: true
    entity_managers:
        postgres:
            connection: postgres
            mappings:
                AppBundle:
                   type:      annotation
                   dir:       Entity\Postgres
        oracle:
            connection: oracle
            mappings:
                AppBundle:
                  type:       annotation
                  dir:        Entity\Oracle

      

And my folder structure looks like this:

AppBundle
    |___Controller
    |      |___EntityController.php
    |
    |___Entity
           |___Postgres
           |     |___SomePostgresBasedEntity.php
           |
           |___Oracle
                 |___SomeOracleBasedEntity.php

      

Now I don't know exactly how this method works, and how it is supposed to know about mapping, if not via configuration. But if I call it that, for example:

 $em = $this->getDoctrine()->getManagerForClass("AppBundle:Oracle\\SomeOracleBasedEntity");

      

... I am getting an Object Manager for Postgres.

But if I just switch the entity manager config by putting one for oracle first, the previous call works, but the following:

 $em = $this->getDoctrine()->getManagerForClass("AppBundle:Postgres\\SomePostgresBasedEntity");

      

Update 1

getManagerForClass()

Loops through each manager and, for each of them, checks if the class is "continuous":

    foreach ($this->managers as $id) {
        $manager = $this->getService($id);

        if (!$manager->getMetadataFactory()->isTransient($class)) {
            return $manager;
        }
    }

      

It comes down to AnnotationDriver->isTransient()

. Here the doc says the following:

A class is not transient if it is annotated with annotation from AnnotationDriver :: entityAnnotationClasses.

@Entity

seems to be one of those annotations that makes a class non-transient. But then, how can any of my essences be transient at all? How can a driver distinguish an entity belonging to a particular manager based solely on their annotations? I must have missed something in the higher level classes.

Update 2

The method works when using yml

mappings.

I expected this behavior. The difference comes from the implementations of the isTransient () method in different drivers. The isTransient FileDriver implementation returns true

if the metadata file exists in dir:

the display configuration directory .

I would expect AnnotationDriver to only look for annotations on objects contained in the specified directory dir:

, but seems to ignore this setting. Or should I use another one?

+1


source to share


1 answer


Finally I have decided. The solution used a parameter prefix

.

entity_managers:
    postgres:
        connection: postgres
        mappings:
            AppBundle:
                type: annotation
                dir: Entity\Postgres
                prefix: AppBundle\Entity\Postgres
                alias: Postgres
    oracle:
        connection: oracle
        mappings:
            AppBundle:
                type: annotation
                dir: Entity\Oracle
                prefix: AppBundle\Entity\Oracle
                alias: Oracle

      

Explanation



The parameter prefix

is passed to the appropriate Entity Manager service and added to the property entityNamespaces

, which has a default value AppBundle/Entity

. The annotation driver then checks the annotations in that particular namespace, while the File Driver checks for existing mapping files in the directory specified by the parameter dir

. (This parameter alias

is optional.)

At least as I understand it.

+1


source







All Articles