Symfony2 ManytoMany双向关系 - 如何手动保存 [英] Symfony2 ManytoMany bidirectional relationship - How to persist manually

查看:140
本文介绍了Symfony2 ManytoMany双向关系 - 如何手动保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用2个输入字段和一个提交按钮的表单。第一个字段是一个简单的下拉列表(类别),但另一个是标签输入字段(Tag),您可以一次输入多个标签。两个字段仅接受预定义的输入选项。



类别选项值在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆