2

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

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

这是 tags 属性的配置,以防万一:

/**
 * @ORM\ManyToMany(targetEntity="Tag")
 * @ORM\JoinTable(name="story__story_tags",
 *   joinColumns={@ORM\JoinColumn(name="story_id", referencedColumnName="id")},
 *   inverseJoinColumns={@ORM\JoinColumn(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])

从第 3 行到最后一行可以看到,我的实体已被索引到 elasticsearch 中,它仅包含 1 个标签:“test”。在此之后,您可以看到 2 个重复的查询试图将标签 #9 与故事 #130 相关联。有谁知道为什么会发生这种情况?

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

谢谢!

4

3 回答 3

0

好吧,我已经设法找到一种使用臭名昭著的黑客“解决”这个问题的方法。除非没有其他办法,否则我不太可能接受这是正确的答案,所以如果您知道解决此问题的好方法,请务必回复。

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

/**
 * 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 \Doctrine\Common\Collections\ArrayCollection());
    parent::create($object);

    // ...then add them again and update.
    $object->setTags($tags);
    $this->getModelManager()->update($object);
}

当然必须有一个更整洁的解决方案?

于 2012-09-11T15:33:34.917 回答
0

这是__construct():

$this->Tags = new \Doctrine\Common\Collections\ArrayCollection() ;

您必须对所有一对多和多对多关系执行此操作。

于 2012-09-12T09:20:53.373 回答
0

此解决方案工作正常:

public function __construct()
{
    $this->tags = new ArrayCollection();
}

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

下次不添加重复键

于 2015-11-15T12:57:38.577 回答