Symfony2 ManytoMany bidirektionale Beziehung - So bleiben Sie manuell bestehen
Ich arbeite an einem Formular mit 2 Eingabefeldern und einer Senden-Schaltfläche. Das erste Feld ist ein einfaches Dropdown-Feld (Kategorie), das andere Feld ist ein Tags-Eingabefeld (Tag), in das Sie mehrere Tags gleichzeitig eingeben können. Beide Felder akzeptieren nur vordefinierte Eingabemöglichkeiten.
Die Werte der Kategorieoptionen sind in Javascript fest codiert:
categories = [
{"id": 1, "categoryname": "standard"},
{"id": 2, "categoryname": "premium"},
{"id": 3, "categoryname": "gold"}
];
Die Optionen für das Tag werden aus dem @ abgerufetag
Tabelle in der Datenbank. Hier ist der Screenshot der Datenbanktabellen:
Die Entitäten "Category" und "Tag" sind mit der bidirektionalen Beziehung "ManytoMany" von Doctrine verknüpft, wobei die Kategorie die besitzende Seite ist.
Hinwei: Ich verwende Symfony @ nicformType
um das Formular zu erstellen, habe ich stattdessen Javascript verwendet.
Das Javascript funktioniert einwandfrei und ich erhalte die Eingabedaten in meinem Controller.Proble ist, dass ich nie eine ManytoMany-Beziehung manuell beibehalten habe. Ich habe die Dokumentation gelesen, bin mir aber nicht sicher, ob ich etwas verpasst habe.
Hier ist die Tag-Entität 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;
}
}
Hier ist die Entität Category 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;
}
}
Hier ist der Controller 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();
}
Das$form_data
ist ein Array mit der Eingabekategorie und den hinzugefügten Tags. Es sieht aus wie das
$form_data = [
['id' => 3, 'categoryname' => 'gold'],
[
['id' => 1, 'tagname' => 'wifi'],
['id' => 4, 'tagname' => 'geyser'],
['id' => 2, 'tagname' => 'cable']
]
];
Doch es bleibt nicht bestehen. Dasvar_dump($category);
das ausgewählte Kategorieobjekt mit der Kategorie @ anzeigid
undcategoryname
, aber das zugehörigetags
Eigenschaft ist leer.
Hier ist der Screenshot der Ausgabe:
Irgendwelche Ideen
Schnelle Frage auf der Seite: Muss ich @ hinzufügcascade={"persist"}
zu beiden Seiten der Beziehungsdefinition hier?
BEARBEITEN Hier habe ich hart codiert$form_data
anstatt Eingabedaten wie oben zu verwenden. DasDefaultController.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();
}
Der Reglerausgang:
ie Sie das @ sehen könntags
-Eigenschaft des Kategorieobjekts ist noch leer.
Hoffentlich hilft dies dabei, das Problem besser zu verstehen. Bitte um Antwort..