Symfony2和SonataAdmin:ManyToMany字段在创建时入两次(导致重复的主键错误),但在更新时工作



我正在尝试向Story实体添加标记。我创建了自己的捆绑包、表单类型和数据转换器来使用textext,我认为一切都很好。。。但事实证明,只有在向现有故事添加标签时才会出现这种情况。如果我在创建故事的同时尝试添加标记,我会引发异常,因为它试图在联接表中创建两次记录,导致重复的主键错误。

我不认为问题出在我的自定义表单类型和数据转换器上,因为我在将请求绑定到表单后,但在持久化之前,已经调试到了控制器中,这里的一切似乎都很好——我的故事实体只包含我添加的标记,没有重复的标记。

以下是标签属性的配置,以防有帮助:

/**
 * @ORMManyToMany(targetEntity="Tag")
 * @ORMJoinTable(name="story__story_tags",
 *   joinColumns={@ORMJoinColumn(name="story_id", referencedColumnName="id")},
 *   inverseJoinColumns={@ORMJoinColumn(name="tag_id", referencedColumnName="id")}
 * )
 */
protected $tags;

以下是我的日志输出摘录:

INSERT INTO stories (created_at, updated_at, published_at, author_id, media_id, title, short_title, summary, text, slug, active, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ({"1":{"date":"2012-09-11 15:07:20","timezone_type":3,"timezone":"Europe/London"},"2":{"date":"2012-09-11 15:07:20","timezone_type":3,"timezone":"Europe/London"},"3":{"date":"2012-09-11 14:56:00","timezone_type":3,"timezone":"Europe/London"},"4":10,"5":68,"6":"Story with tags","7":"","8":"Test","9":"<p>test</p>","10":"story-with-tags","11":true,"12":"media"})
INSERT INTO story__media (id, story_media_id, media_size, show_caption) VALUES (?, ?, ?, ?) ({"1":"130","2":null,"3":"0","4":false})
SELECT s0_.slug AS slug0 FROM stories s0_ LEFT JOIN story__gallery s1_ ON s0_.id = s1_.id LEFT JOIN story__media s2_ ON s0_.id = s2_.id LEFT JOIN story__competition s3_ ON s0_.id = s3_.id WHERE s0_.slug LIKE 'story-with-tags-872875%' AND s0_.id <> ? ([130])
INSERT INTO story__counters (story_id, hits, shares, comments, updated_at) VALUES (?, ?, ?, ?, ?) ({"1":130,"2":0,"3":0,"4":0,"5":{"date":"2012-09-11 15:07:20","timezone_type":3,"timezone":"Europe/London"}})
INSERT INTO story__sections (story_id, section_id, section_position) VALUES (?, ?, ?) ({"1":130,"2":212,"3":1})
UPDATE stories SET slug = ?, updated_at = ? WHERE id = ? (["story-with-tags-872875",{"date":"2012-09-11 15:07:20","timezone_type":3,"timezone":"Europe/London"},130])
website/story/130 (DELETE) 11.00 ms
website/story/130 (PUT) 5.12 ms
Context: { title: 'Story with tags', summary: Test, text: '<p>test</p>', author: billy-wiggins, publishedAt: 1347371760, tags: [test] }
INSERT INTO story__story_tags (story_id, tag_id) VALUES (?, ?) ([130,9])
INSERT INTO story__story_tags (story_id, tag_id) VALUES (?, ?) ([130,9])

正如你从第三行到最后一行所看到的,我的实体已经被索引到弹性搜索中,它只包含一个标签:"test"。接下来,您可以看到两个重复的查询试图将标签#9与故事#130关联起来。有人知道为什么会发生这种事吗?

是否可以以某种方式使这些插入查询使用INSERT IGNORE语法,因为这至少可以绕过问题。

谢谢!

好吧,我已经设法找到了一种使用气味难闻的黑客"修复"这个问题的方法。除非没有其他方法,否则我不太可能接受这是正确的答案,所以如果你知道解决这个问题的好方法,请一定做出回应。

因为问题只在同时创建我的Story实体和标签时才会出现,所以我扩展了基本Admin类的create方法,如下所示:(准备捏住你的鼻子……现在!)

/**
 * TODO achieve this in a non-smelly way
 * 
 * @param Story $object
 * @return mixed|void
 */
public function create($object)
{
    // Create fails when story has tags, so remove them...
    $tags = $object->getTags();
    $object->setTags(new DoctrineCommonCollectionsArrayCollection());
    parent::create($object);
    // ...then add them again and update.
    $object->setTags($tags);
    $this->getModelManager()->update($object);
}

肯定会有一个更整洁的解决方案吗?

假设这是__construct():

$this->Tags = new DoctrineCommonCollectionsArrayCollection() ;

你必须为所有一个人和多个人的关系做到这一点。

此解决方案运行良好:

public function __construct()
{
    $this->tags = new ArrayCollection();
}
public function addTag(Tag $tag)
{
    if (!this->tags->contains($tag)) {
        $this->tags->add($tag);
    }
}

下次时未添加重复密钥

相关内容

  • 没有找到相关文章

最新更新