简体   繁体   中英

OneToMany association is not stored with Doctrine

Currently in the process of creating a Member with one or more Subscriptions. Everything works well and the output is what I expect it to be.

When the Subscription is associated with the specified Member and I dump this object before the class finishes, it is all there correctly processed.

The code:

/** @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();
}

The dump (snippet) after this loop:

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
        }
      ]
    }
  }
}

As far as I see, everything went well. The object is not dirty anymore. Whenever the function is done, meaning I leave the page, the object does not contain it's subscriptions anymore.

Here is a dump (snippet) after I load the Member again on a different page:

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: []
    }
  }
]

My Entities;

Member

/**
 * @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;
    }
}

Doctrine will only take care of the owning side of your relationships. Check also the documentation chapter 11: Association Updates: Owning Side and Inverse Side .

So to be able to get subscriptions from your Member entity you need to manually update the inverse side. The best way to do so is probably like this:

Inside your MemberSubscription :

//...

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

//...

Update:

Your subscriptions PersistentCollection will is lazy-loaded. You can see in the output that the collection is not initialized:

-initialized: false

Simply dumping the collection will not load the elements. Once you will interact with your lazy-loaded PersistentCollection Doctrine will load/initialize the collection for you and it will be populated with its Member elements.

You can also do this manually by calling initialize(); . After that you will see the elements when you dump the variable again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM