Hola,
Tengo un formulario para actualizar datos (update), y si lo relleno con datos incorrentos entonces no valida y retorna al mismo formulario mostrando el error. Hasta ahí todo bien. Lo malo es que los datos se persisten igual.
Tengo un servicio "LastOnlineListener" (event: kernel.terminate
), que actualiza la fecha y hora que el usuario carga una pagina en la entidad User
, que no tiene en relación con la entidad de que se actualiza en el formulario. El flush
en este servicio guarda también los datos del formulario no validado.
¿Hay alguna forma de evitar esto? Gracias
Respuestas
Según comentas, en el listener se actualiza también la entidad relacionada con el formulario. Aunque no soy ningún experto en Doctrine, entiendo que si esto pasa es porque dentro del formulario has hecho un persist()
de la entidad errónea incluso aunque el formulario no sea válido. Si el error fuera este, sólo deberías hacer el persist
después del $form->isValid()
.
Por otra parte, aunque la documentación de Doctrine es horrible y muy confusa, creo que al método flush()
le puedes pasar la instancia de una entidad concreta y sólo tendrá en cuenta esa entidad para hacer sus cosas y no todas las entidades que se hayan marcado con el método persist()
.
@javiereguiluz
Gracias por responder, es muy raro lo que sucede, hace poco mas de un año que estoy con este proyecto (personal) y espero ponerlo online pronto, pero cuando parece que estoy cerca cada vez se aleja más por diferentes problemas que surgen.
He probado ->flush(obj)
pero no me funciona.
Este es mi código:
public function editAction($id) { $em = $this->getDoctrine()->getManager(); $request = $this->getRequest(); $obj = $em->getRepository('ObjBundle:Obj')->findOneBy(array( 'id' => $id, )); $form = $this->createForm(new ObjEditType(), $obj); $form->handleRequest($request); if ($form->isValid()) { $em->persist($obj); $em->flush(); //... return $this->redirect($this->generateUrl('home')); } $em->detach($obj); // con esta línea funciona bien return $this->render('FBundle:ZZZ:edit.html.twig', array('form' => $form->createView())); }
Lo raro es que $em->persist($obj);
está dentro del if($form->isValid())
y aun así se actualiza los cambios no válidos del formulario.
Para que funcione bien y no se guarde los cambios cuando el formulario no valida, tuve que agregar la linea $em->detach($obj);
que no se qué hace exactamente, solo lo vi en el código fuente y lo coloqué. También funciona con $em->refresh($object);
.
/** * Detaches an object from the ObjectManager, causing a managed object to * become detached. Unflushed changes made to the object if any * (including removal of the object), will not be synchronized to the database. * Objects which previously referenced the detached object will continue to * reference it. * * @param object $object The object to detach. * * @return void */ public function detach($object); /** * Refreshes the persistent state of an object from the database, * overriding any local changes that have not yet been persisted. * * @param object $object The object to refresh. * * @return void */ public function refresh($object);
@javiereguiluz sos grosso.
Pd: el 95% de lo que yo se sobre symfony, lo se gracias a vos. y sin vos no hubiera empezado mi proyecto personal (hace 1 año), porque sólo PHP es casi imposible por el tamaño de la web que estoy haciendo, y porque utilizar otros framework (de la calidad de symfony) documentados en español no existen.
@AjPZZO
Lo primero un pequeño comentario que no está relacionado con tu pregunta, pero creo que te puede ayudar. La primera parte del código de tu acción editAction()
se puede simplificar de esta manera:
use Symfony\Component\HttpFoundation\Request; // ... public function editAction(Request $request, $id) { $em = $this->getDoctrine()->getManager(); $obj = $em->getRepository('ObjBundle:Obj')->find($id); $form = $this->createForm(new ObjEditType(), $obj); $form->handleRequest($request); // ... }
Respecto al error que se está produciendo, esta línea $form->handleRequest($request);
hace que la entidad se modifique con los datos enviados mediante el formulario, sean válidos o no. Hasta ahí todo normal.
Pero si no has marcado con persist()
a esa entidad, no debería importar que sus datos se hayan modificado porque no la vas a persistir. En algún sitio está sucediendo esto pero no logro entender dónde.
El método detach()
que comentas hace precisamente lo contrario que persist()
. Le dice a Doctrine que ya no se preocupe de esa entidad, ya que no quiere seguir persistiendo sus cambios en la base de datos. Obviamente hay que utilizarla con mucho cuidado para evitar efectos indeseados.
@javiereguiluz
Gracias por el consejo del $request
,
Con respecto a lo otro, lo raro es que no hay ningun otro persist()
fuera de ese if
, cuando hice estos formularios, la version de symfony era la 2.3, y creo haberlo testeado bien y no tenian este error, ahora esta actualizada a la ultima, creo que debe tratarse de un bug. Otra cosa no se que pensar,
Por ahora lo reparo con el detach()
o el refresh($object)
y estare atento a nuevas actualizaciones de symfony.
@AjPZZO