In a recent project (virtualidentityag/hydra-twitter) i tried to create a Symfony2 form field that lets you choose from the list of entities managed by doctrine (so that the user could decide which entity he wants to map a REST-resultset to). I thought that there was no easy way doing this. Heres how i found a solution.

My first guess was to kind of reflect the schema and found that there exists a SchemaManager. Unfortunately creating a schema using the schema manager was not helping, i could not derive the class names of the entities. However i was able to find a list of tables that are currently managed (i am working inside a symfony2 controller):

$em = $this->getDoctrine()->getManager();
$tables = $em->getConnection()->getSchemaManager()->listTables();

The tables are all instances of Doctrine\DBAL\Schema\Table. You cannot derive the entity class from the table directly because doctrine does not work that way. Doctrine uses a Hydrator to “deserialize” the result from the database to your own entities.

My second guess was to search Doctrine for functions that would return the full qualified class name for a Table instance. Unfortunately this was not possible. In fact i have to admit that i did not fully understand how doctrine resolves the names that you use in DQL-statements because the dql-parsing code of Doctrine is quite complicated.

As i remembered from Symfony2 example code you do not have to provide the FQCN in a DQL query – it suffices to write “YourBundle:YourEntity”. Doctrine will then automatically find your Entity-class name by getting the namespace for your bundle, supposing you have a sub-namespace called “Entity” and then construct the class name from that coding convention.

But my code should not be dependent from bundle names or any bundle at all. So hard coding this into my code (and following the Symfony/Doctrine convention) was no option for this situation.

On further investigation of Doctrines code i found a way to list all namespaces that are searched for entities using the configuration-object of Doctrine:

$em = $this->getDoctrine()->getManager();
$namespaces = $em->getConfiguration()->getEntityNamespaces();

From here on the next step was easy although dirty and i didn’t like what i’ve done here:

// warning: don't use that!
$entities = array();
$em = $this->getDoctrine()->getManager()
$tables = $em->getConnection()->getSchemaManager()->listTables();
$namespaces = $em->getConfiguration()->getEntityNamespaces();
foreach ($tables as $table) {
    foreach ($namespaces as $namespace) {
        if (class_exists($namespace.'\\'.$table->getName())) {
            break;
        }
    }
    $entities[] = $namespace.'\\'.$table->getName();
}

I showed the code to a friend of mine (@traktorjosh) and he pointed out, that my code would stop working the moment somebody decides to give his table a different name using the Table-annotation: @Table(name=”notWorking”).

Back to start. I was frustrated. Then i decided to take a look at the UpdateCommand that is called when you execute “app/console doctrine:schema:update”. And there i found what i desperately was looking for: the getAllMetadata-method. Who thought it might hide here? The method returns a list of ClassMetadata objects which let you “Get fully-qualified class name of this persistent class”. So the final solution was straight forward:

$entities = array();
$em = $this->getDoctrine()->getManager();
$meta = $em->getMetadataFactory()->getAllMetadata();
foreach ($meta as $m) {
    $entities[] = $m->getName();
}

Finally it looks like i have found a clean method listing all entities. Again hours of headache for 4 lines of code. If you have any suggestions how to make this better please let me know.