symfony3 form example php ajax forms symfony doctrine2

php - example - Symfony2: Impedir el duplicado en la base de datos con formulario Many to One



symfony form (3)

A juzgar por su relación, quiere evitar que el mismo estudiante se agregue dos veces a la entidad Parents . Hay un truco simple para eso, la clase ArrayCollaction tiene un método llamado contains que devuelve true si un valor u objeto ya se encuentra en la colección. Una mejor in_array .

Por lo tanto, debe verificar dentro del sumador si $parent ya contiene el $student que está a punto de agregarse y actuar en consecuencia. Como se muestra a continuación:

public function addStudent(/Cole/BackendBundle/Entity/Student $student) { if (!$this->students->contains($student)) { $this->students[] = $students; } return $this; }

Tengo un formulario para padres incrustado en otra forma Estudiante que contiene los datos de los padres de un alumno con una asociación de Muchos a uno.

Cuando se registra un nuevo registro de estudiantes, sus padres se registran en otra tabla de la base de datos. Entonces, si un nuevo estudiante que es hermano de una necesidad existente para registrarse, lo que significa que los padres ya están registrados en la base de datos, se debe evitar que los padres se registren nuevamente en la base de datos, solo se puede actualizar.

Me dijeron que esto se soluciona usando transformadores de datos, pero no sé cómo usarlo. Si alguien pudiera ayudarme, lo agradecería. Aquí dejo el código:

StudentType.php

//... ->add(''responsible1'', new ParentsType(),array(''label'' => ''Mother'')) ->add(''responsible2'', new ParentsType(),array(''label''=> ''Father''))

Entidad Padres

/** * @var integer * * @ORM/Column(name="id", type="integer") * @ORM/Id * @ORM/GeneratedValue(strategy="AUTO") */ private $id; //National identity document //we have removed "@UniqueEntity(fields={"NID"}, message="...")" //so you can put any NID on the form and then check its existence to insert or not. /** * @var string * * @ORM/Column(name="NID", type="string", length=10) * @Assert/NotBlank() */ private $nid; //more properties... /** * @ORM/OneToMany(targetEntity="Student", mappedBy="$responsible1") * @ORM/OneToMany(targetEntity="Student", mappedBy="$responsible2") */ private $students; //... public function addStudent(/Cole/BackendBundle/Entity/Student $students) { $this->students[] = $students; return $this; } public function removeStudent(/Cole/BackendBundle/Entity/Student $students) { $this->students->removeElement($students); } public function getStudents() { return $this->students; }

Entidad Estudiante

//... /** * @ORM/ManyToOne(targetEntity="Parents", inversedBy="students", cascade={"persist"}) */ private $responsible1; /** * @ORM/ManyToOne(targetEntity="Parents", inversedBy="students", cascade={"persist"}) */ private $responsible2; //... public function setResponsible1($responsible1) { $this->responsible1 = $responsible1; return $this; } public function getResponsible1() { return $this->responsible1; } public function setResponsible2($responsible2) { $this->responsible2 = $responsible2; return $this; } public function getResponsible2() { return $this->responsible2; }

ParentsRepository.php

class ParentsRepository extends EntityRepository { public function findResponsible($nid) { return $this->getEntityManager()->createQuery( ''SELECT p FROM BackendBundle:Parents p WHERE p.nid=:nid'') ->setParameter(''nid'',$nid) ->setMaxResults(1) ->getOneOrNullResult(); } }

StudentController.php

/** * Creates a new Student entity. * */ public function createAction(Request $request) { $entity = new Student(); $form = $this->createCreateForm($entity); $form->handleRequest($request); if ($form->isValid()) { $responsible1 = $em->getRepository(''BackendBundle:Parents'')->findResponsible($entity->getResponsible1()->getNid()); $responsible2 = $em->getRepository(''BackendBundle:Parents'')->findResponsible($entity->getResponsible2()->getNid()); if($responsible1){ $entity->setResponsible1($responsible1->getId()); } if($responsible2){ $entity->setResponsible2($responsible2->getId()); } $entity->getResponsible1()->setUsername($entity->getResponsible1()->getNid()); $entity->getResponsible2()->setUsername($entity->getResponsible2()->getNid()); $entity->getResponsible1()->setPassword($entity->getResponsible1()->getNid()); $entity->getResponsible2()->setPassword($entity->getResponsible2()->getNid()); $em = $this->getDoctrine()->getManager(); $em->persist($entity); $em->flush(); return $this->redirect($this->generateUrl(''student_show'', array(''id'' => $entity->getId()))); } return $this->render(''BackendBundle:Student:new.html.twig'', array( ''entity'' => $entity, ''form'' => $form->createView(), )); }

Con el código anterior intento resolver el problema pero me da error para persistir datos a la base de datos y no me deja agregar a la base de datos, pero si usa el siguiente código para probar el nuevo alumno crea y asigna padres correspondientes no los crea de nuevo (suponiendo que ya se haya creado antes).

$responsible1 = $em->getRepository(''BackendBundle:Parents'')->findResponsible(4); //The number corresponds to the id of the parent $responsible2 = $em->getRepository(''BackendBundle:Parents'')->findResponsible(5); $entity->setResponsible1($responsible1->getId()); $entity->setResponsible2($responsible2->getId());

No sé si lo que estoy haciendo es correcto. Leí algo para usar Data Transformers o el oyente de eventos como PrePersist y Preupdate, pero no sé cómo usarlo.

Gracias de antemano por sus respuestas.


Aquí están mis pensamientos , de los comentarios, dijiste que estás usando un documento de identidad nacional (con la esperanza de que sea una representación entera), conviértelo en la clave principal de la tabla principal y haz que sea único, así que cuando el segundo alumno es el hermano de un otro alumno ingresa los mismos detalles y los envía, la base de datos generará un error, manejará ese error y continuará

editar: puede que ni siquiera sea necesario convertir la identidad nacional en la clave principal, solo que sea única, se supone que debes hacer esto independientemente, te perdiste esta.

puede usar el tipo de formulario de entidad de Symfony para cargar (ajax) la entidad principal cuando el alumno ingresa la identidad nacional


En lugar de

if($responsible1){ $entity->setResponsible1($responsible1->getId()); } if($responsible2){ $entity->setResponsible2($responsible2->getId()); } $entity->getResponsible1()->setUsername($entity->getResponsible1()->getNid()); $entity->getResponsible2()->setUsername($entity->getResponsible2()->getNid()); $entity->getResponsible1()->setPassword($entity->getResponsible1()->getNid()); $entity->getResponsible2()->setPassword($entity->getResponsible2()->getNid());

puedes escribir

if($responsible1){ $entity->setResponsible1($responsible1); } if($responsible2){ $entity->setResponsible2($responsible2); }

Y debería funcionar.

Pero creo que una mejor solución será agregar un detector de eventos al evento FormEvents::SUBMIT . Este evento le permite cambiar los datos de la representación normalizada de los datos del formulario. Entonces, todo lo que necesitas hacer es algo como esto:

public function onSubmit(FormEvent $event) { $student = $event->getData(); if ($student->getResponsible1()) { $parentNid = $student->getResponsible1()->getNid(); // here you check the database to see if you have a parent with this nid // if a parent exists, replace the current submitted parent data with the parent entity existing in your db }

Espero que esto ayude. Avísame si tengo que dar más detalles.