草庐IT

php - Symfony2 ManytoMany 双向关系 - 如何手动持久化

coder 2024-04-21 原文

我正在处理一个包含 2 个输入字段和一个提交按钮的表单。第一个字段是一个简单的下拉列表(类别),而另一个是标签输入字段(标签),您可以在其中一次输入多个标签。这两个字段仅接受预定义的输入选项。

类别选项值在 javascript 中硬编码:

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

tag 的选项是从数据库中的tag 表中获取的。这是数据库表的屏幕截图:

Category 和 Tag 实体与 Doctrine 的 ManytoMany 双向关系相关联,类别是拥有方。

注意:我没有使用 Symfony formType 创建表单,而是使用了 javascript。

javascript 工作正常,我在我的 Controller 中获取了输入数据。 问题 是我从来没有手动坚持多对多关系。 阅读了文档,但不确定我是否遗漏了什么。

这是标签实体(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;
    }
}

这是类别实体 (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;
    }

}

这是 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();
}

$form_data 是一个包含输入类别和添加标签详细信息的数组。它看起来像这样:

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

它仍然没有持续存在。 var_dump($category); 显示带有类别 idcategoryname 的选定类别对象,但关联的 tags属性为空。

这是输出的屏幕截图:

有什么想法吗?

侧面的快速问题:我是否需要在此处的关系定义的两侧添加 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();

        // 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();
    }

Controller 输出:

如您所见,类别对象的 tags 属性仍然是空的。

希望这有助于更好地理解问题。 等待回应...

最佳答案

通过做得到合适的标签实体时

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

$tag的值不就是一个集合数组吗?

那么可能会做以下事情吗?

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

关于php - Symfony2 ManytoMany 双向关系 - 如何手动持久化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38306116/

有关php - Symfony2 ManytoMany 双向关系 - 如何手动持久化的更多相关文章

  1. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  2. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  3. ruby - 如何在 Ruby 中创建双向 SSL 套接字 - 2

    我正在构建一个连接到服务器并等待数据的客户端Ruby库,但也允许用户通过调用方法发送数据。我使用的机制是有一个初始化套接字对的类,如下所示:definitialize@pipe_r,@pipe_w=Socket.pair(:UNIX,:STREAM,0)end我允许开发人员调用以将数据发送到服务器的方法如下所示:defsend(data)@pipe_w.write(data)@pipe_w.flushend然后我在一个单独的线程中有一个循环,我从连接到服务器的socket和@pipe_r中选择:defsocket_loopThread.newdosocket=TCPSocket.new

  4. ruby-on-rails - Rails - 双向 "friendship"模型(续) - 2

    这是这个问题的延续:OriginalQuestion(SO)这个问题的答案涉及以下一组模型:classUser:friendships#...endclassFriendship'User',:foreign_key=>'friend_id'end如果说,我有一个用户并且我想获得他或她的id是友谊模型上的:user_idFK的所有“友谊”,这很好用。但是,当我运行类似的东西时@user.friendships.friends我希望它返回该用户是友谊中的:user或:friend的所有用户记录-因此,换句话说,返回该用户参与的所有友谊。希望以上内容有意义。我对Rails还是很陌生,希望有

  5. 【数据结构和算法】实现带头双向循环链表(最复杂的链表) - 2

    前文,我们实现了认识了链表这一结构,并实现了无头单向非循环链表,接下来我们实现另一种常用的链表结构,带头双向循环链表。如有仍不了解单向链表的,请看这一篇文章(7条消息)【数据结构和算法】认识线性表中的链表,并实现单向链表_小王学代码的博客-CSDN博客目录前言一、带头双向循环链表是什么?二、实现带头双向循环链表1.结构体和要实现函数2.初始化和打印链表3.头插和尾插4.头删和尾删5.查找和返回结点个数6.在pos位置之前插入结点7.删除指定pos结点8.摧毁链表三、完整代码1.DSLinkList.h2.DSLinkList.c3.test.c总结前言带头双向循环链表,是链表中最为复杂的一种结

  6. ruby-on-rails - Rails 还是 Sinatra? PHP程序员入门学习哪个好? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。我使用PHP的时间太长了,对它感到厌倦了。我也想学习一门新语言。我一直在使用Ruby并且喜欢它。我必须在Rails和Sinatra之间做出选择,那么您会推荐哪一个?Sinatra真的不能用来构建复杂的应用程序,它只能用于简单的应用程序吗?

  7. ruby - 通过 node-sass 的 Symfony assetic sass 过滤器? - 2

    我在让asseticsass过滤器与node-sass而不是ruby​​替代品一起工作时遇到了一些困难。我的config.yml文件中有以下配置:assetic:debug:"%kernel.debug%"use_controller:falsebundles:[]write-to:"%kernel.root_dir%/../web/assets"read_from:"%kernel.root_dir%/../web/assets"node:"%%PROGRAMFILES%%\nodejs\\node.exe"node_paths:["%%USERPROFILE%%\\AppData\

  8. ruby-on-rails - PHP 魔术方法 __call、__get 和 __set 的 Ruby 等价物 - 2

    我很确定Ruby有这些(等同于__call、__get和__set),否则find_by将如何在Rails中工作?也许有人可以举一个简单的例子来说明如何定义与find_by相同的方法?谢谢 最佳答案 简而言之你可以映射__调用带有参数的method_missing调用__设置为方法名称以'='结尾的method_missing调用__获取不带任何参数的method_missing调用__调用PHPclassMethodTest{publicfunction__call($name,$arguments){echo"Callingob

  9. ruby - Lisp - 是否适合网络编程/应用程序(交互式)? ruby 的方式是? php的方式是? - 2

    Lisp是否适合Web编程/应用程序(交互式),就像ruby​​和php一样?需要考虑的事情是:易于使用可部署性难度(尤其是对于编程初学者而言)(编辑)在阅读PaulGraham'sessay之后,我特别提到了CommonLisp.将是我的第一门编程语言。在这方面。这样做合适吗?我听说Clojure的宏功能不如CommonLisp的强大,这就是我尝试学习Clojure的原因。它教授编程并且非常强大。 最佳答案 Lisp是一个语系,而不是单一的语言。为了稍微回答您的问题,是的,存在用于各种Lisp方言的Web框架,例如用于Common

  10. ruby - Ruby 程序的持久哈希表? - 2

    我的Ruby脚本需要一个小型非结构化数据库。不是Sqlite,更像是持久哈希表的东西可以完美地工作,只要它可以存储基本的Ruby结构(数组、字符串、哈希等-都是可序列化的)并且不会在Ruby脚本崩溃时被破坏。我知道有很多类似Perl和Tie::Hash的解决方案,所以可能有一些类似Ruby的gem。那会是什么gem?编辑:据我所知,PStore和yaml解决方案是基于每次更改时读取、解码、重新编码和写入整个数据库。这不仅需要所有这些都适合内存,而且是O(n^2)。所以它们似乎都不是特别好的解决方案。 最佳答案 有PStore在Rub

随机推荐