Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Form que no valida se actualiza igual

31 de agosto de 2014

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

#1

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

31 agosto 2014, 20:56
#2

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

1 septiembre 2014, 8:29
#3

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

1 septiembre 2014, 10:25
#4

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

1 septiembre 2014, 17:36