Doctrine flush() error: Expected value of type "Doctrine\Common\Collections\Collection|array"

Doctrine flush() error: Expected value of type "Doctrine\Common\Collections\Collection|array"

我在 Symfony(使用 Doctrine)中使用多对多关系时遇到一个奇怪的问题,我以前在 symfony 项目中从未遇到过多对多关系,我找不到任何区别其他项目。

我有两个实体 Product 和 Tag,并且彼此之间存在多对多关系。不幸的是,如果我尝试将产品添加到标签,反之亦然,错误

Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "TestBundle\Entity\Product#$tags", got "TestBundle\Entity\Tag" instead.

出现。 用于向产品添加标签的代码:

    $tag1 = $em->getRepository('TestBundle:Tag')->findOneBy(array(
        'tag' => "Bla"
    ));

    $tag1->addProduct($product);
    $em->persist($tag1);
    $em->persist($product);

    $em->flush();

当然,变量$tag1 和$product 都包含一个有效的实体。 多对多关系的YAML文件(我删掉了不相关的部分):

TestBundle\Entity\Tag:
type: entity
table: tags
repositoryClass: TestBundle\Repository\TagRepository
id:
    id:
        type: integer
        id: true
        generator:
            strategy: AUTO
fields:
    tag:
        type: string
        length: 255
        unique: true
manyToMany:
    products:
        targetEntity: Product
        mappedBy: tags
lifecycleCallbacks: {  }

产品:

TestBundle\Entity\Product:
type: entity
table: products
repositoryClass: TestBundle\Repository\ProductRepository
id:
    id:
        type: integer
        id: true
        generator:
            strategy: AUTO
fields:
    name:
        type: string
        length: 255
        unique: true
manyToOne:
    manufacturer:
        targetEntity: Manufacturer
        inversedBy: products
        joinColumn:
            name: manufacturer_id
            referencedColumnName: id
            onDelete: CASCADE
manyToMany:
    tags:
        targetEntity: Product
        inversedBy: products
        joinTable:
            name: tags2products
            joinColumns:
                tag_id:
                    referencedColumnName: id
            inverseJoinColumns:
                product_id:
                    referencedColumnName: id
lifecycleCallbacks: {  }

setter 和 getter 函数也不包含任何特殊技巧: Tag.php 实体文件包含:

 /**
 * Constructor
 */
public function __construct()
{
    $this->product = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add product
 *
 * @param \TestBundle\Entity\Product $product
 *
 * @return Tag
 */
public function addProduct(\TestBundle\Entity\Product $product)
{
    $product->addTag($this);
    $this->product[] = $product;
    return $this;
}


public function removeProduct(\TestBundle\Entity\Product $product)
{
    $this->product->removeElement($product);
}

/**
 * Get products
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getProducts()
{
    return $this->products;
}

虽然 Product.php 包含:

 /**
 * Add tag
 *
 * @param \TestBundle\Entity\Tag $tag
 *
 * @return Product
 */
public function addTag(Tag $tag)
{
    $this->tags->add($tag);
    //$this->tags[] = $tag;
    return $this;
}

/**
 * Remove tag
 *
 * @param \TestBundle\Entity\Tag $webpage
 */

public function removeTag(Tag $tag)
{
    $this->tags->removeElement($tag) ;
}

/**
 * Get webpages
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getTags()
{
    return $this->tags;
}

我还尝试添加一个 $this->tags = new ArrayCollection();给产品的构造者,但它没有改变任何东西。

此外,在产品中添加、读取和持久化标签也没有问题。一旦我调用 $em->flush().

就会抛出错误

有人知道为什么我的 Product 实体需要数组集合吗?我从来没有告诉他期待一个!非常感谢您!

错误告诉您,您要刷新的实体 TestBundle\Entity\Product 的 属性“#tags”包含类型为 TestBundle\Entity\Tag 的对象,而不是集合这个对象的。 Doctrine 期望这个 collection/array 因为 属性 的元数据表明 TestBundle\Entity\Product 与 TestBundle\Entity\Tag 处于多对多关系中,并且关系是通过 [=23= 完成的] “#tags”。如果出现以下情况,就会发生这种情况:

//You did this
$this->tags = $tag;

//instead of what you actually did which is correct
$this->tags->add($tag);

//Or 

$this->tags[] = $tag;

但是您在此处发布的代码不应产生该异常。

您确定没有其他地方调用访问器方法来更改 TestBundle\Entity\Product 的标签 属性 吗?类似事件监听器的东西?

终于知道是什么奇怪的问题了。感谢 Alexandr Cosoi 确认我尝试添加实体的方式。 问题是我没有注意到的配置错误。

manyToMany:
tags:
    targetEntity: Product
    inversedBy: products
    joinTable:
        name: tags2products
        joinColumns:
            tag_id:
                referencedColumnName: id
        inverseJoinColumns:
            product_id:
                referencedColumnName: id

targetEntity 已设置为 Product,但必须设置为 "Tag"。更改它只是按预期解决了我的问题。 :)