type isvalid form fields collection array php forms symfony doctrine2

php - isvalid - symfony form validation



Symfony2 ManytoMany relación bidireccional: cómo persistir manualmente (1)

Al obtener la entidad de etiqueta apropiada haciendo

$tag = $em->getRepository(''AppBundle:Tag'')->findOneById($tagId);

¿No es el valor de $ tag una matriz de colecciones?

¿Entonces posiblemente haga lo siguiente?

$category->addTag($tag[0]);

Estoy trabajando en un formulario con 2 campos de entrada y un botón de enviar. El primer campo es un simple menú desplegable (Categoría) pero el otro es un campo de entrada de etiquetas (Etiqueta) donde puede ingresar varias etiquetas a la vez. Ambos campos aceptan solo opciones de entrada predefinidas.

Los valores de la opción de categoría están codificados en javascript:

categories = [ {"id": 1, "categoryname": "standard"}, {"id": 2, "categoryname": "premium"}, {"id": 3, "categoryname": "gold"} ];

Las opciones para la etiqueta se obtienen de la tabla de tag en la base de datos. Aquí está la captura de pantalla de las tablas de la base de datos:

Las entidades de Categoría y Etiqueta están asociadas con la relación bidireccional ManytoMany de Doctrine, siendo la categoría propietaria.

Nota : No estoy utilizando Symfony formType para crear el formulario, en su lugar he usado JavaScript para eso.

El javascript funciona bien y obtengo los datos de entrada en mi controlador. El problema es que nunca he insistido en una relación ManytoMany manualmente. Leí los documentos pero no estoy seguro si me perdí algo.

Aquí está la entidad Tag ( Tag.php ):

<?php namespace AppBundle/Entity; use Doctrine/Common/Collections/ArrayCollection; use Doctrine/ORM/Mapping as ORM; use AppBundle/Entity/Category; /** * Tag * * @ORM/Table(name="tag") * @ORM/Entity(repositoryClass="AppBundle/Repository/TagRepository") */ class Tag { /** * @var int * * @ORM/Column(name="Id", type="integer") * @ORM/Id * @ORM/GeneratedValue(strategy="AUTO") */ protected $id; /** * * @var string * * @ORM/Column(name="TagName", type="string") */ protected $tagname; /** * @ORM/ManyToMany(targetEntity="Category", mappedBy="tags") */ protected $categories; /** * @return ArrayCollection */ public function __construct() { $this->categories = new ArrayCollection(); } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set id * * @return Tag */ public function setId($id) { return $this->id = $id; } /** * Set tagname * * @param string $tagname * @return Tag */ public function setTagname($tagname) { $this->tagname = $tagname; return $this; } /** * Get tagname * * @return string */ public function getTagname() { return $this->tagname; } /** * Add categories * * @param /AppBundle/Entity/Category $categories * @return Tag */ public function addCategory(/AppBundle/Entity/Category $categories) { $this->categories[] = $categories; return $this; } /** * Remove categories * * @param /AppBundle/Entity/Category $categories */ public function removeCategory(/AppBundle/Entity/Category $categories) { $this->categories->removeElement($categories); } /** * Get categories * * @return /Doctrine/Common/Collections/Collection */ public function getCategories() { return $this->categories; } }

Aquí está la entidad Category.php ( Category.php ):

<?php namespace AppBundle/Entity; use Doctrine/Common/Collections/ArrayCollection; use Doctrine/ORM/Mapping as ORM; use AppBundle/Entity/Tag; /** * Category * * @ORM/Table(name="category") * @ORM/Entity(repositoryClass="AppBundle/Repository/CategoryRepository") */ class Category { /** * @var int * * @ORM/Column(name="Id", type="integer") * @ORM/Id * @ORM/GeneratedValue(strategy="AUTO") */ protected $id; /** * * @var string * * @ORM/Column(name="CategoryName", type="string") */ protected $categoryname; /** * * @var string * * @ORM/Column(name="Description", type="string") */ protected $description; /** * @ORM/ManyToMany(targetEntity="Tag", cascade={"persist"}, inversedBy="categories") */ protected $tags; /** * @return ArrayCollection */ public function __construct() { $this->tags = new ArrayCollection(); } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set id * * @return Category */ public function setId($id) { return $this->id = $id; } /** * Set categoryname * * @param string $categoryname * @return Category */ public function setCategoryname($categoryname) { $this->categoryname = $categoryname; return $this; } /** * Get categoryname * * @return string */ public function getCategoryname() { return $this->categoryname; } /** * Set description * * @param string $description * @return Category */ public function setDescription($description) { $this->description = $description; return $this; } /** * Get description * * @return string */ public function getDescription() { return $this->description; } /** * Add tags * * @param /AppBundle/Entity/Tag $tags * @return Category */ public function addTag(/AppBundle/Entity/Tag $tags) { $this->tags[] = $tags; return $this; } /** * Remove tags * * @param /AppBundle/Entity/Tag $tags */ public function removeTag(/AppBundle/Entity/Tag $tags) { $this->tags->removeElement($tags); } /** * Get tags * * @return /Doctrine/Common/Collections/Collection */ public function getTags() { return $this->tags; } }

Aquí está el controlador ( DefaultController.php ):

/** * @Route("/formsubmit", options={"expose"=true}, name="my_route_to_submit") */ public function submitAction(Request $request) { $jsonString = file_get_contents(''php://input''); $form_data = json_decode($jsonString, true); $em = $this->getDoctrine()->getManager(); // set category details $categoryId = $form_data[0][''id'']; $category = $em->getRepository(''AppBundle:Category'')->findOneById($categoryId); // set tags $len = count($form_data[1]); for ($i = 0; $i < $len; $i++) { $tagId = $form_data[1][$i][''id'']; $tag = $em->getRepository(''AppBundle:Tag'')->findOneById($tagId); $category->addTag($tag); } // persist/save in database $em->persist($category); $em->flush(); }

$form_data es una matriz con la categoría de entrada y los detalles de las etiquetas agregadas. Se parece a esto:

$form_data = [ [''id'' => 3, ''categoryname'' => ''gold''], [ [''id'' => 1, ''tagname'' => ''wifi''], [''id'' => 4, ''tagname'' => ''geyser''], [''id'' => 2, ''tagname'' => ''cable''] ] ];

Aún así no persiste. El var_dump($category); muestra el objeto de categoría seleccionado con id categoría y nombre de categoryname , pero la propiedad de tags asociada está vacía.

Aquí está la captura de pantalla de la salida:

¿Algunas ideas?

Pregunta rápida al costado : ¿Necesito agregar cascade={"persist"} a ambos lados de la definición de relación aquí?

EDITAR: Aquí, he codificado $form_data lugar de usar datos de entrada como lo hice anteriormente. The DefaultController.php :

/** * @Route("/formsubmit", options={"expose"=true}, name="my_route_to_submit") */ public function submitAction(Request $request) { $form_data = [ [''id'' => 3, ''categoryname'' => ''gold''], [ [''id'' => 1, ''tagname'' => ''wifi''], [''id'' => 4, ''tagname'' => ''geyser''], [''id'' => 2, ''tagname'' => ''cable''] ] ]; $em = $this->getDoctrine()->getManager(); // set category details $categoryId = $form_data[0][''id'']; $category = $em->getRepository(''AppBundle:Category'')->findOneById($categoryId); // set tags $len = count($form_data[1]); for ($i = 0; $i < $len; $i++) { $tagId = $form_data[1][$i][''id'']; $tag = $em->getRepository(''AppBundle:Tag'')->findOneById($tagId); // $tag->addCategory($category); $category->addTag($tag); } var_dump($category); exit; // persist/save in database $em->persist($category); $em->flush(); }

La salida del controlador:

Como puede ver, la propiedad de tags del objeto de categoría todavía está vacía.

Espero que esto ayude a entender mejor el problema. Esperando respuesta...