without unidirectional one many generate from foreign symfony doctrine2 entity one-to-many many-to-one

unidirectional - Symfony2/Doctrine2-ManyToOne-Guardar el lado inverso



many to many relation doctrine (2)

Soy nuevo en Symfony y Doctrine.

Tengo una entidad "Usuario" y una entidad "Tipo". Un usuario puede tener un tipo de favorito y un tipo puede tener muchos usuarios que tienen ese tipo específico como favorito. Entonces necesito una relación de Muchos (Usuario) a Uno (Tipo).

Lo implementé y funciona bien (principalmente). Pero hay una cosa que no entiendo.

Si hago algo así, funciona:

$user = new User(); $type = new Type(); $user->setFavoriteType($type); $em->persist($user); $em->persist($type); $em->flush();

Los objetos se generan y almacenan en la base de datos. Y el favorite_type_id está configurado correctamente. Así que cambiar el lado propietario funciona como se espera .

Pero si agrego el usuario al lado inverso (solamente) y purgo el administrador de entidades, el tipo_de_privado no está configurado.

$user = new User(); $type = new Type(); $type->getUsers()->add($user); //same with $type->addUser($user); $em->persist($user); $em->persist($type); $em->flush();

¿Porqué es eso? ¿Hay alguna razón por la cual no funciona desde el lado inverso? ¿Realmente tengo que configurar esto manualmente? Si manipulo el método addUser en la entidad type como "$ user-> setFavoriteType ($ this)" funciona. Pero, ¿no debería ser esa la tarea de la doctrina?

La documentación dice

Cuando se actualiza una asociación bidireccional, Doctrine solo verifica estos cambios en uno de los dos lados. Esto se llama el lado dueño de la asociación.

Entonces parece ser el comportamiento deseado, ¿es así? ¿Pero por qué? Debido al rendimiento? Razones semánticas?

Me alegraría si alguien pudiera explicarme eso o decirme lo que estoy haciendo mal.


Consulte la documentación de Doctrine en cascada. . Esto debería ayudarlo a comenzar con lo que parece que quiere hacer, rápida y fácilmente, agregando cascade={"persist"} y borrando su caché (para reconstruir el caché de metadatos de Doctrine).


Esto se debe a que, fundamentalmente, cuando se considera la persistencia, Doctrine asigna las entidades de PHP directamente a las tablas de la base de datos. En su caso, los Usuarios y Tipos conceptualmente tienen una relación Muchos a Uno, pero a nivel de la base de datos la relación se representa completamente en la tabla Usuario - un Usuario tiene un tipo favorito, y la Mesa de Usuario tiene una columna de tipo_de_pralicio. Aunque podemos pensar en las Entidades de Tipo que tienen una lista de Usuarios para los cuales son los favoritos, esto esencialmente también se deriva al mirar la tabla de Usuario, no hay nada en la tabla Tipo.

La configuración del mapeo de entidades en Doctrine le dice a Doctrine cuál es la relación entre las Entidades y permite que Doctrine le proporcione ciertos métodos de acceso convenientes como $type->getUsers() , pero no cambia la forma en que se almacenan los datos subyacentes. Si utilizo $user->setFavoriteType , estoy manipulando datos para los cuales hay una correspondencia directa con la base de datos, pero, de forma predeterminada, si llamo $type->addUser no lo soy, el propósito principal de hacer este tipo de llamadas fuera de -the-box es mantener actualizadas las entidades hidratadas con las que está trabajando en la actualidad, en ausencia de simplemente tirar los objetos y volver a buscarlos desde el DB.

Por supuesto, ha visto que puede personalizar addUser para que también llame a setFavoriteType , o configure la persistencia en cascada como lo sugiere Shon M, para que el comportamiento se parezca un poco más a cómo podría esperarlo / esperarlo. Puede parecer una pérdida de tiempo dejarlo así desde el principio, pero sospecho que los desarrolladores de Doctrine han elegido conscientemente implementar la funcionalidad necesaria de la manera más simple posible, mientras la documentan claramente y ofrecen varias alternativas fáciles si eso es lo que tú '' re after, de ese modo atiende a todos de una forma u otra. Nos guste o no, qué datos están en la base de datos y qué datos se están ejecutando en PHP post-hidratación son cosas técnicamente diferentes, especialmente en un modelo como Doctrine donde la actividad de DB se pospone hasta que el desarrollador lo solicite, y tiene mucho sentido ¡para hacer todo eso tan explícito como sea posible!