Symfony2 ManytoMany双向关系 - 如何手动保存 [英] Symfony2 ManytoMany bidirectional relationship - How to persist manually
问题描述
类别选项值在javascript中是硬编码的:
categories = [
{id:1,categoryname:standard},
{id:2,categoryname:premium},
{id:3,categoryname:gold}
];
标签的选项是从标签中获取
数据库中的表。以下是数据库表的截图:
类别和标签实体与Doctrine的ManytoMany双向关系相关联,类别是拥有方。
注意:我没有使用Symfony formType
创建表单,而我已经使用了javascript。
JavaScript工作正常,我得到我的控制器中的输入数据。 问题是,我从来没有手动持续使用ManytoMany关系。
阅读文档但不知道我是否错过任何内容。
这是标签实体( Tag.php
):
<?php
命名空间AppBundle\Entity;
使用Doctrine\Common\Collections\ArrayCollection;
使用Doctrine\ORM\Mapping作为ORM;
使用AppBundle\Entity\Category;
/ **
*标签
*
* @ ORM\Table(name =tag)
* @ ORM\Entity repositoryClass =AppBundle\Repository\TagRepository)
* /
class标签{
/ **
* @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() ;
}
/ **
*获取id
*
* @return integer
* /
public function getId )
{
return $ this-> id;
}
/ **
*设置ID
*
* @return标签
* /
public function setId($ id)
{
return $ this-> id = $ id;
}
/ **
*设置标记名
*
* @param string $ tagname
* @return标签
* /
public function setTagname($ tagname)
{
$ this-> tagname = $ tagname;
return $ this;
}
/ **
*获取标记名
*
* @return string
* /
public function getTagname )
{
return $ this-> tagname;
}
/ **
*添加类别
*
* @param \AppBundle\Entity\Category $ categories
* @return标签
* /
public function addCategory(\AppBundle\Entity\Category $ categories)
{
$ this-> categories [] = $ categories ;
return $ this;
}
/ **
*删除类别
*
* @param \AppBundle\Entity\Category $ categories
* /
public function removeCategory(\AppBundle\Entity\Category $ categories)
{
$ this-> categories-> removeElement($ categories);
}
/ **
*获取类别
*
* @return \Doctrine\Common\Collections\Collection
* /
public function getCategories()
{
return $ this-> categories;
}
}
这是类别实体( Category.php
):
<?php
命名空间AppBundle\Entity;
使用Doctrine\Common\Collections\ArrayCollection;
使用Doctrine\ORM\Mapping作为ORM;
使用AppBundle\Entity\Tag;
/ **
*类别
*
* @ ORM\Table(name =category)
* @ ORM\Entity repositoryClass =AppBundle\Repository\CategoryRepository)
* /
class类别{
/ **
* @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() ;
}
/ **
*获取id
*
* @return integer
* /
public function getId ){
return $ this-> id;
}
/ **
*设置ID
*
* @return类别
* /
public function setId $ id){
return $ this-> id = $ id;
}
/ **
*设置categoryname
*
* @param string $ categoryname
* @return类别
* /
public function setCategoryname($ categoryname){
$ this-> categoryname = $ categoryname;
return $ this;
}
/ **
*获取类别名
*
* @return string
* /
public function getCategoryname ){
return $ this-> categoryname;
}
/ **
*设置描述
*
* @param string $ description
* @return类别
* /
public function setDescription($ description){
$ this-> description = $ description;
return $ this;
}
/ **
*获取描述
*
* @return string
* /
public function getDescription ){
return $ this-> description;
}
/ **
*添加标签
*
* @param \AppBundle\Entity\Tag $ tags
* @return类别
* /
public function addTag(\AppBundle\Entity\Tag $ tags){
$ this-> tags [] = $ tags;
return $ this;
}
/ **
*删除标签
*
* @param \AppBundle\Entity\Tag $ tags
* /
public function removeTag(\AppBundle\Entity\Tag $ tags){
$ this-> tags-> removeElement($ tags);
}
/ **
*获取标签
*
* @return \Doctrine\Common\Collections\Collection
* /
public function getTags(){
return $ this-> tags;
}
}
这是控制器( DefaultController.php
):
/ **
* @Route (/ formsubmit,options = {expose= true},name =my_route_to_submit)
* /
public function submitAction(Request $ request){
$ jsonString = file_get_contents 'PHP://输入');
$ form_data = json_decode($ jsonString,true);
$ em = $ this-> getDoctrine() - > getManager();
//设置类别详细信息
$ categoryId = $ form_data [0] ['id'];
$ category = $ em-> getRepository('AppBundle:Category') - > findOneById($ categoryId);
//设置标签
$ len = count($ form_data [1]); ($ i = 0; $ i $ $ len; $ i ++)
{
$ tagId = $ form_data [1] [$ i] ['id'];
$ tag = $ em-> getRepository('AppBundle:Tag') - > findOneById($ tagId);
$ category-> addTag($ tag);
}
//持久/保存在数据库
$ em-> persist($ category);
$ em-> flush();
}
$ form_data
是一个具有输入类别和添加标签细节的数组。它看起来像这样:
$ form_data = [
['id'=> 3,'categoryname'=> 'gold'],
[
['id'=> 1,'tagname'=> 'wifi'],
['id'=> 4,'tagname'=> 'geyser'],
['id'=> 2,'tagname'=> 'cable']
]
];
仍然不存在。 var_dump($ category);
显示所选类别对象,类别为 id
和 categoryname
,但相关的标签
属性为空。
以下是输出的屏幕截图:
任何想法?
侧面的快速问题:是否需要将 cascade = {persist}
添加到两边的关系定义在这里?
编辑:在这里,我硬编码 $ form_data
而不是像上面那样使用输入数据。
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();
//设置类别详细信息
$ categoryId = $ form_data [0] ['id'];
$ category = $ em-> getRepository('AppBundle:Category') - > findOneById($ categoryId);
//设置标签
$ len = count($ form_data [1]); ($ 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);
退出;
//持久/保存在数据库
$ em-> persist($ category);
$ em-> flush();
}
控制器输出:
正如您可以看到标签
属性的类别对象仍然是空的。
希望这将有助于更好地理解问题。
等待响应...
通过执行
获取适当的标签实体 $ tag = $ em-> getRepository('AppBundle:Tag') - > findOneById($ tagId);
$ tag的集合数组不是$ tag的值?
所以可能要做以下事情?
$ category-> addTag($ tag [0]);
I am working on a form with 2 input fields and a submit button. The first field is a simple dropdown (Category) but the other one is a tags-input field(Tag) where u can enter multiple tags at a time. Both fields accept predefined input options only.
The category option values are hardcoded in javascript:
categories = [
{"id": 1, "categoryname": "standard"},
{"id": 2, "categoryname": "premium"},
{"id": 3, "categoryname": "gold"}
];
The options for tag are fetched from the tag
table in the database. Here is the screenshot of the database tables:
The Category and Tag entities are associated with Doctrine's ManytoMany bidirectional relationship, with category being the owning side.
Note: I am not using Symfony formType
to create the form, instead I've used javascript for that.
The javascript works fine and I get the input data in my controller. Problem is that i've never persisted a ManytoMany relation manually. Did read the docs but not sure if I missed anything.
Here is the Tag entity (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;
}
}
Here is the Category entity (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;
}
}
Here is the 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();
}
The $form_data
is an array with the input category and added tags detail. It looks like this:
$form_data = [
['id' => 3, 'categoryname' => 'gold'],
[
['id' => 1, 'tagname' => 'wifi'],
['id' => 4, 'tagname' => 'geyser'],
['id' => 2, 'tagname' => 'cable']
]
];
Still it doesn't persist. The var_dump($category);
display the selected category object with category id
and categoryname
, but the associated tags
property is empty.
Here is the screenshot of the output:
Any Ideas?
Quick question on the side: Do I need to add cascade={"persist"}
to both the sides of relationship definition here?
EDIT: Here, I've hard-coded $form_data
instead of using input data as I did above. 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();
}
The controller output:
As you can see the tags
property of the category object is still empty.
Hope this'll help understand the issue better. Awaiting response...
When getting the appropriate tag entity by doing
$tag = $em->getRepository('AppBundle:Tag')->findOneById($tagId);
Isn't the value of $tag an array of collections?
So possibly do the following?
$category->addTag($tag[0]);
这篇关于Symfony2 ManytoMany双向关系 - 如何手动保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!