Doctrine:在引用表中有多对多列的额外列

时间:2017-01-26 09:31:46

标签: symfony doctrine-orm

我遇到了Symfony3 / doctrine2和多对多列的问题。我刚开始用它开发

是的,我看到帖子:Doctrine2: Best way to handle many-to-many with extra columns in reference table 但老实说,我不明白为什么它不能用我的代码......

我被困2天,看着谷歌(他不是我的朋友),阅读文件......我的大脑不明白......

请帮助我理解原因。

问题

我有会员和地址实体。我想按成员或所有成员的地址提供所有地址。所以,ManyToMany在学说中。 在我的联接表上,我需要一个额外的列favorite_address 所以,我需要有3个实体:Member,Address,MemberAddress

实体成员:

class Member implements AdvancedUserInterface
{

....

/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Member\MemberAddress", mappedBy="member", cascade={"all"})
 * @ORM\JoinTable(name="member_address",
 *      joinColumns={@ORM\JoinColumn(name="member_id", referencedColumnName="id")})
 */
private $addresses;

....

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

/**
 * Add an address
 * @param Address $address
 */
public function addAddress(\AppBundle\Entity\Address\Address $address)
{
    // Ici, on utilise l'ArrayCollection vraiment comme un tableau
    $this->addresses[] = $address;
}

/**
 * Remove an address
 * @param Address $address
 */
public function removeAddress(\AppBundle\Entity\Address\Address $address)
{
    // Ici on utilise une méthode de l'ArrayCollection, pour supprimer la catégorie en argument
    $this->addresses->removeElement($address);
}

/**
 * Get all addresses
 * @return ArrayCollection
 */
public function getAddresses()
{
    return $this->addresses;
}

实体地址:

class Address
{
....

/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Member\MemberAddress", mappedBy="address", cascade={"all"})
 * @ORM\JoinTable(name="member_address",
 *      joinColumns={@ORM\JoinColumn(name="address_id", referencedColumnName="id")})
 */
private $members;

....

/**
 * Add a member
 * @param Member $member
 */
public function addMember(\AppBundle\Entity\Member\Member $member)
{
    // Ici, on utilise l'ArrayCollection vraiment comme un tableau
    $this->members[] = $member;
}

/**
 * Remove a member
 * @param Member $member
 */
public function removeMember(\AppBundle\Entity\Member\Member $member)
{
    // Ici on utilise une méthode de l'ArrayCollection, pour supprimer la catégorie en argument
    $this->members->removeElement($member);
}

/**
 * Get all members
 * @return ArrayCollection
 */
public function getMembers()
{
    return $this->members;
}

最后一个Entity:MemberAddressReference

class MemberAddress
{
/**
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/** @ORM\ManyToOne(targetEntity="AppBundle\Entity\Member\Member", inversedBy="addresses")
 *  @ORM\JoinColumn(name="member_id", referencedColumnName="id")
 */
protected $member;

/** @ORM\ManyToOne(targetEntity="AppBundle\Entity\Address\Address", inversedBy="members")
 *  @ORM\JoinColumn(name="address_id", referencedColumnName="id")
 */
protected $address;

/** @ORM\Column(type="boolean") */
protected $isFavorite;

完成,控制器

class MemberAddressController extends Controller
{

public function createAction(Request $request){
    ....
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $currentDate = new \DateTime("now");

        $em = $this->getDoctrine()->getManager();
        $address = new Address();
        $memberAddress = new MemberAddress();

        $address->setType($form['type']->getData());
        $address->setCreated($currentDate);
        $address->setModified($currentDate);

        $memberAddress->setMember($member);
        $memberAddress->setAddress($address);
        $memberAddress->setFavorite(1);

        $em->persist($member);
        $em->persist($address);
        $em->persist($memberAddress);

        $member->addAddress($address);

        $em->flush();

        dump($member);
        die();
    }

那么,出了什么问题

我收到此错误:

Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\Member\Member#$addresses", got "AppBundle\Entity\Address\Address" instead.
是的,类型不好,我理解,但为什么他不好?

public function addAddress(\AppBundle\Entity\Address\Address $address)
{
    // Ici, on utilise l'ArrayCollection vraiment comme un tableau
    $this->addresses[] = $address;
}

addAddress取地址对象,没有?那他为什么要等阵?

请帮帮我,我疯了......

1 个答案:

答案 0 :(得分:0)

我不了解 memberAdress 实体的目标。如果要创建OneToMany双向关系,则不需要创建第三个实体。 根据学说文件:

   /** @Entity */
class Product
{
    // ...
    /**
     * One Product has Many Features.
     * @OneToMany(targetEntity="Feature", mappedBy="product")
     */
    private $features;
    // ...

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

/** @Entity */
class Feature
{
    // ...
    /**
     * Many Features have One Product.
     * @ManyToOne(targetEntity="Product", inversedBy="features")
     * @JoinColumn(name="product_id", referencedColumnName="id")
     */
    private $product;
    // ...
}

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html

修改

如果您想使用第三个实体,则您的地址与您的会员之间不存在关系。它们只是由第三方联系在一起。 所以你应该这样做:

会员实体:

class Member implements AdvancedUserInterface
{
/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Member\MemberAddress", mappedBy="member", cascade={"all"})
 */
private $addresses;

地址实体

class Address
{
/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Member\MemberAddress", mappedBy="address", cascade={"all"})
 */
private $members;

如果您想要成员的所有地址,则需要创建自定义存储库以将地址表与其他两个表连接。