onetmany关联不存储在Doctrine中


OneToMany association is not stored with Doctrine

当前正在创建具有一个或多个订阅的成员。一切都运行良好,输出是我所期望的。

如果Subscription与指定的Member相关联,并且我在类结束之前转储了这个对象,那么它就被正确地处理了。

代码:

/** @var Member $member */
foreach ($members as $member) {
    $subscription = new MemberSubscription();
    $subscription->setBillingDate(new DateTime('now'));
    $subscription->setMember($member);
    $subscription->setPaid(true);
    $this->em->persist($member);
    $this->em->persist($subscription);
    $this->em->flush();
}

循环后的转储(代码片段):

Member {#1649 ▼
  #id: 3577
  <...>
  #subscriptions: PersistentCollection {#1616 ▼
    -snapshot: array:1 [ …1]
    -owner: Member {#1649}
    -association: array:15 [ …15]
    -em: EntityManager {#1452 …10}
    -backRefFieldName: "member"
    -typeClass: ClassMetadata {#1601 …}
    -isDirty: false
    -initialized: false
    -coll: ArrayCollection {#1628 ▼
      -_elements: array:1 [▼
        0 => MemberSubscription {#1669 ▼
          #id: 67
          #member: Member {#1649}
          #billing_date: DateTime {#1668 ▶}
          #paid: true
        }
      ]
    }
  }
}
在我看来,一切都进行得很顺利。对象不再脏了。每当函数完成时,也就是说我离开了页面,对象就不再包含它的订阅了。

下面是我在另一个页面上再次加载Member后的转储(代码片段):

array:26 [▼
  "id" => 3577
  <..>
  "paid" => PersistentCollection {#1569 ▼
    -snapshot: []
    -owner: Member {#1552 ▶}
    -association: array:15 [ …15]
    -em: EntityManager {#1396 …10}
    -backRefFieldName: "member"
    -typeClass: ClassMetadata {#1565 …}
    -isDirty: false
    -initialized: false
    -coll: ArrayCollection {#1573 ▼
      -_elements: []
    }
  }
]

我的实体;

/**
 * @ORM'Entity(repositoryClass="Foo'Member'MemberRepository")
 * @ORM'Table(name="Foo_Member", options={"charset"="latin1","collate"="latin1_swedish_ci"})
 */
class Member
{
    /**
     * @ORM'Id
     * @ORM'GeneratedValue
     * @ORM'Column(type="integer")
     * @var int|null
     */
    protected $id;
    /**
     * @ORM'OneToMany(targetEntity="MemberSubscription", mappedBy="member")
     */
    protected $subscriptions;
    <..>
    /**
     * @return int|null
     */
    public function getId()
    {
        return $this->id;
    }
    <..>
    /**
     * @return mixed
     */
    public function getSubscriptions()
    {
        return $this->subscriptions;
    }
    /**
     * @param mixed $subscriptions
     */
    public function setSubscriptions($subscriptions)
    {
        $this->subscriptions = $subscriptions;
        return $this;
    }
}

MemberSubscription

/**
 * @ORM'Entity()
 * @ORM'Table(name="Foo_MemberSubscription", options={"charset"="latin1","collate"="latin1_swedish_ci"})
 */
class MemberSubscription
{
    /**
     * @ORM'Id
     * @ORM'GeneratedValue
     * @ORM'Column(type="integer")
     * @var int|null
     */
    protected $id;
    /**
     * @ORM'ManyToOne(targetEntity="Member", inversedBy="subscriptions")
     */
    protected $member;
    /**
     * @ORM'Column(type="datetime", nullable=true)
     * @var DateTime|null
     */
    protected $billing_date;
    /**
     * @ORM'Column(type="boolean", nullable=true)
     * @var bool
     */
    protected $paid;
    /**
     * @return int|null
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * @param int|null $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }
    /**
     * @return mixed
     */
    public function getMember()
    {
        return $this->member;
    }
    /**
     * @param mixed $member
     */
    public function setMember($member)
    {
        $this->member = $member;
    }
    /**
     * @return null|DateTime
     */
    public function getBillingDate()
    {
        return $this->billing_date;
    }
    /**
     * @param null|DateTime $billing_date
     */
    public function setBillingDate($billing_date)
    {
        $this->billing_date = $billing_date;
    }
    /**
     * @return boolean
     */
    public function isPaid()
    {
        return $this->paid;
    }
    /**
     * @param boolean $paid
     */
    public function setPaid($paid)
    {
        $this->paid = $paid;
    }
}

原则只关心你关系中拥有的那一面。另请参阅文档第11章:关联更新:主侧和反侧。

因此,为了能够从您的Member实体获得订阅,您需要手动更新逆侧。最好的方法可能是这样:

Inside your MemberSubscription:

//...
/**
 * @param mixed $member
 */
public function setMember($member)
{
    $this->member = $member;
    $member->addSubscription($this);
}
//...

更新:

您的订阅PersistentCollection将是惰性加载的。您可以在输出中看到集合没有初始化:

-initialized: false

简单地转储集合不会加载元素。一旦您将与惰性加载的PersistentCollection学说交互,它将为您加载/初始化集合,并将填充其Member元素。

您也可以通过调用initialize();手动执行此操作。之后,当您再次转储变量时,您将看到这些元素。