2012-08-17 10 views
10

tengo este códigoDoctrina 2 no persiste la relación de la propiedad de lado de uno a muchos

// ONE to many Bidir -- inverse side 
    /** 
    * @ORM\OneToMany(targetEntity="Item", mappedBy="Room", cascade={"persist"}) 
    **/ 
    protected $items; 

El otro lado

// ONE to many Bidir-- own side 
    /** 
    * @ORM\ManyToOne(targetEntity="Room", inversedBy="items") 
    * @ORM\JoinColumn(name="room_id", referencedColumnName="id") 
    **/ 
    protected $room; 

Mi problema es que me voy a la página del artículo y selecciono habitación, entonces puedo ver los elementos en la Sala preselecetd página

Pero si vuelvo a ir a la página de habitaciones y trato de multiselección muchos artículos, a continuación, aquellos que no se conservan

EDITAR: he visto que solo está sucediendo para la relación OneToMany. Para Manyto Muchos están trabajando bien

Edit2:

Estoy hablando de la zona backend donde tengo la forma y de selección donde puedo seleccionar varios elementos. Este formulario/código CRUD/controladores están genrated por doctrina. ASÍ NO necesito agregar ninguna función adicional. De cualquier manera este es mi código del controlador

$editForm = $this->createForm(new RoomType(), $entity); 


     $request = $this->getRequest(); 

     $editForm->bindRequest($request); 
     if ($editForm->isValid()) { 
      $em->persist($entity); 
      $em->flush(); 

Cuando trato de caminar a través de controlador como este

foreach($entity->getItems() as $item) 
     echo $item; 

entonces puedo ver todos los artículos thye allí. Entonces significa que todos los elementos están ahí en el objeto principal pero no los persiste. No sé por qué.

Si se debe, problema en el reverso. ¿Cómo puedo reducir la relación de debido a inversa e inversa a ser dueño de

+1

No estoy seguro de cómo se ve el código, o su base de datos, algunos ejemplos serían útiles. – Asciiom

Respuesta

10

Su código es incorrecto, en función de sus comentarios en las anotaciones.

Este es el lado poseer, porque se especifica el atributo inversedBy:

/** 
* ONE to many Bidir-- Inverse side 
* @ORM\ManyToOne(targetEntity="Room", inversedBy="items") 
* @ORM\JoinColumn(name="room_id", referencedColumnName="id") 
**/ 
protected $room; 

Este es el lado inverso (porque tiene el atributo mappedBy):

/** 
* ONE to many Bidir -- owning side 
* @ORM\OneToMany(targetEntity="Item", mappedBy="Room", cascade={"persist"}) 
**/ 
protected $items; 

Así su código dice: Item es el lado propietario, Room es el lado inverso.

El poseer lado de una relación bidireccional debe referirse a su lado inverso por uso de la inversedBy atributo de la OneToOne, ManyToOne, o declaración mapeo ManyToMany. El atributo invertedBy designa el campo en la entidad que es el lado inverso de la relación .

Para que sea más limpia:

lado

La propietaria tiene que utilizar el atributo inversedBy del OneToOne, ManyToOne, o declaración de mapeo ManyToMany.El atributo invertedBy contiene el nombre del campo de asociación en el lado inverso.

Mientras que, por el lado inverso:

El lado inverso de una relación bidireccional debe referirse a su lado propietario por uso de la mappedBy atributo de la OneToOne, Declaración de mapeo OneToMany, o ManyToMany. El atributo mappedBy designa el campo en la entidad que es el propietario de la relación .

Y, de nuevo:

El lado inverso tiene que utilizar el atributo mappedBy del OneToOne, OneToMany, o declaración de mapeo ManyToMany. El atributo mappedBy contiene el nombre del campo de asociación en el lado propietario.

Además, otra consideración importante:

ManyToOne es siempre el lado propietario de un assocation bidireccional.

OneToMany es siempre el lado inverso de una assocation bidireccional

Así, por la persistencia de los artículos en el lado inverso (habitación), usted tiene que comprobar qué elemento ha sido seleccionado/no seleccionado y si la habitación ya contiene ese artículo o no.

+2

Es posible que me equivoque al decir qué lado es propietario e inverso, pero el código debería funcionar en ambas direcciones. I treid cascade {persist} en cada lado y en ambos también, pero no funcionó. incluso si no hay ningún elemento para esa habitación, y selecciono 5 elementos, nada va en la base de datos. y esto está sucediendo para una clase más. entonces creo que necesito agregar algo en mi código para que ocurra lo contrario. ¿Está mi código correcto independientemente de lo que es propietario y del lado inverso? – user825904

3

Simplemente use su lazo para establecer la habitación. El artículo se debe al lado y usted está editando el lado inverso (habitación). Symfony2 nunca actualiza los lados debidos mientras edita uno inverso.

La solución más simple para usted es utilizar bucle antes habitación persistente:

foreach($entity->getItems() as $item){ 
    $item->setRoom($room); 
} 

y cascada en el lado inverso:

/** 
* @ORM\OneToMany(targetEntity="Item", mappedBy="Room", cascade={"persist"}) 
**/ 
protected $items; 

Para mis proyectos que hice solución reutilizable basado en eventos de recolección de los oyentes. Si tiene habilidades de tiempo &, le recomiendo que haga lo mismo

+0

Creo que también necesito persistir el elemento en el ciclo también. ¿De qué evento de recaudación está hablando? ¿Me puede dar alguna referencia o algún enlace? – user825904

+0

Si tienes cascada en el lado inverso, no tienes que persistir. Si lo obtuvo antes, probablemente todos los datos del objeto se guardaron, pero sin sala de padres. –

+0

Lea sobre eventos de formulario: http: // stackoverflow.com/questions/9651095/description-of-symfony2-form-events, la recopilación solo forma incrustaciones de elementos –

Cuestiones relacionadas