tutorial symfony2 generate entitymanagerinterface consultas php symfony doctrine2 doctrine

php - symfony2 - generate entities symfony 4



Symfony 2.8: Doctrine getManagerForClass() no devuelve el administrador de entidad correcto (1)

Por fin, lo resolví. La solución estaba usando el parámetro de 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

Explicación

El parámetro de prefix se pasa al servicio correspondiente de Entity Manager, y se agrega a la propiedad entityNamespaces , que de lo contrario AppBundle/Entity a ser AppBundle/Entity . El Controlador de Anotación verificará las anotaciones en ese espacio de nombres específico , mientras que el Controlador de Archivos verifica los archivos de mapeo existentes en el directorio especificado a través del parámetro dir . (El parámetro de alias no es obligatorio).

Al menos, así es como lo entiendo.

tl; dr ¿Cómo el método getManagerForClass() descubre qué administrador de entidades es el correcto para una clase específica?

Creé un controlador genérico que debería poder manejar acciones básicas para diferentes entidades. También tengo conexiones con dos bases de datos diferentes, así que estoy usando dos administradores de entidades.

En mi controlador, estoy tratando de usar el método getManagerForClass () de Doctrine para encontrar qué administrador usar para cada clase, como se explica en este blog y esta respuesta SO .

Pero el método no parece diferenciar a mis dos administradores de entidades y simplemente devuelve el primero en la configuración.

Mi acción de controlador comienza así:

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

Esta es mi configuración de Doctrine:

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

Y mi estructura de carpetas es la siguiente:

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

Ahora no sé exactamente cómo funciona el método, y cómo se supone que debe saber sobre el mapeo si no a través de la configuración. Pero si lo llamo de esta manera, por ejemplo:

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

... obtengo el administrador de la entidad para Postgres.

Pero si simplemente cambio la configuración del administrador de entidades, poniendo primero la de oráculo, la llamada anterior funciona, pero la siguiente no:

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

Actualización 1

getManagerForClass() recorre cada administrador y para cada uno, comprueba si la clase es "no transitoria":

foreach ($this->managers as $id) { $manager = $this->getService($id); if (!$manager->getMetadataFactory()->isTransient($class)) { return $manager; } }

Esto llega hasta AnnotationDriver->isTransient() . Aquí el doc dice lo siguiente:

Una clase no es transitoria si está anotada con una anotación de AnnotationDriver :: entityAnnotationClasses.

@Entity parece ser una de esas anotaciones que hace que una clase no sea transitoria. Pero entonces, ¿cómo podría alguna de mis entidades ser transitoria? ¿Cómo podría el conductor distinguir una entidad que pertenece a un administrador específico basándose únicamente en sus anotaciones? Debo haberme perdido algo en las clases de nivel superior.

Actualización 2

El método funciona cuando se utilizan asignaciones de yml .

Esperaba este comportamiento. La diferencia proviene de las implementaciones del método isTransient () en los diferentes controladores. La implementación FileDriver de isTransient devuelve true si el archivo de metadatos existe en el directorio dir: de la configuración de asignación.

Hubiera esperado que AnnotationDriver buscara anotaciones solo en las entidades contenidas en el directorio dir: especificado, pero parece ignorar ese parámetro. ¿O debería usar otro?