我在Symfony(使用Doctrine)中使用多对多关系时遇到一个奇怪的问题,我以前在symfony项目中从未遇到多对多关系,我无法找到任何关系与其他项目的区别。
我有两个实体Product和Tag以及彼此之间的多对多关系。不幸的是,如果我尝试将产品添加到标签或反之,则错误
类型" Doctrine \ Common \ Collections \ Collection | array"的预期值for association field" TestBundle \ Entity \ Product#$ tags",got" TestBundle \ Entity \ Tag"代替。
出现。 用于向产品添加标记的代码:
$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实体需要数组集合吗?我从没告诉他期待一个人!非常感谢你提前!
答案 0 :(得分:2)
错误告诉您正在尝试刷新的实体TestBundle \ Entity \ Product的属性“#tags”包含TestBundle \ Entity \ Tag类型的对象,而不是此对象的集合。 Doctrine期望这个集合/数组,因为该属性的元数据表明TestBundle \ Entity \ Product与TestBundle \ Entity \ Tag处于多对多状态,并且关系是通过属性“#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的tags属性吗?像和事件监听器一样?
答案 1 :(得分:0)
我终于发现了奇怪的问题。感谢Alexandr Cosoi确认我尝试添加实体的方式。 问题是我没有注意到的配置错误。
manyToMany:
tags:
targetEntity: Product
inversedBy: products
joinTable:
name: tags2products
joinColumns:
tag_id:
referencedColumnName: id
inverseJoinColumns:
product_id:
referencedColumnName: id
targetEntity设置为Product但必须设置为" Tag"。改变它只是按预期解决了我的问题。 :)