Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

entityManager save and refresh

I'm trying to save in cascade some object and retrieve it. I have 3 Object over 3 entities.

Entites:

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

    /**
     * @var object $basket
     *
     * @ORM\OneToOne(targetEntity="Entity\Basket", inversedBy="order")
     */
    protected $basket;
...
}

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

    /**
     * @var array $declinations
     *
     * @ORM\OneToMany(targetEntity="Entity\BasketDeclination", mappedBy="basket")
     */
    protected $declinations;

    /**
     * Order owner (reversed side)
     * 
     * @var OrderClient $order
     * 
     * @ORM\OneToOne(targetEntity="Entity\Order", mappedBy="basket")
     */
    protected $order;
...
}

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

    /**
     * @var integer $basket
     *
     * @ORM\ManyToOne(targetEntity="Entity\Basket", inversedBy="declinations")
     */
    protected $basket;
...
}

Object Over Entity:

class OrderObject
{
    function __construct(
        EntityManager $em,
        Order $entity = null,
        BasketObject $basket = null
    )
    {
        $this->em = $em;

        if (!$entity) {
            $this->entity = new Order();

            $this->basket = $basket;
        } else {
            $this->setDataFromEntity($entity);
        }
    }

    protected function setDataFromEntity(Order $entity)
    {
        $basketFactory = new BasketFactory($this->em);

        $this->entity = $entity;

        $this->basket = $basketFactory->getBasket($entity->getBasket()->getId());
    }

    public function save($flush = false)
    {
        // save subObject
        $this->basket->save();

        // set link
        $this->entity->setBasket($this->basket->getEntity());

        $this->em->persist($this->entity);

        if ($flush) {
            $this->em->flush();
        }
    }

    public function refresh()
    {
        $this->em->refresh($this->entity);
        $this->setDataFromEntity($this->entity);
    }
...
}

class BasketObject
{
    function __construct(EntityManager $em, Basket $entity = null)
    {
        $this->em = $em;

        if (!$entity) {
            $this->entity = new Basket();
            $this->declinations = array();
        } else {
            $this->setDataFromEntity($entity);
        }
    }

    protected function setDataFromEntity(Basket $entity)
    {
        $this->entity = $entity;

        $this->declinations = array();
        foreach ($entity->getDeclinations() as $declination) {
            $this->declinations[] = new BasketDeclinationObject($this->em, $declination);
        }
    }

    public function save($flush = false)
    {
        foreach ($this->declinations as $declination) {
            $declination->save();
        }
        $this->em->persist($this->entity);
        if ($flush) {
            $this->em->flush();
        }
    }
...
}

class BasketDeclinationObject
{
    public function __construct(
            EntityManager $em,
            BasketDeclination $entity= null,
            BasketObject $basket = null)
    {
        $this->em = $em;

        if (!$entity) {
            $this->entity = new BasketDeclination();

            $this->basket = $basket;
        } else {
            $this->setDataFromEntity($entity);
        }
    }

    protected function setDataFromEntity(BasketDeclination $entity)
    {
        $this->entity = $entity;

        $declinationFactory = new DeclinationFactory($this->em);
        $this->declination = $declinationFactory->getDeclination($entity->getDeclination()->getId());
    }

    public function save($flush = false)
    {
        if ($this->quantity <= 0) {
            $this->em->remove($this->entity);
            $this->remove = true;
            return ;
        }
        if (!$this->entity->getId()) {
            $this->entity->setBasket($this->basket->getEntity());
        }
        $this->entity->setQuantity($this->quantity);
        $this->em->persist($this->entity);
        if ($flush) {
            $this->em->flush();
        }
    }
...
}

The problem is that in my test when I try for a basket to add BasketDeclination then save the Basket is saved and BasketDeclination too. Then when I $basket->refresh() the basket is refresh and the BasketDeclinaiton is rebuild from entity

BUT when I have an order whith a basket and I add BasketDeclinaiton ($order->basket->addDeclination(...)) When I save all entities are saved then when I refresh the order I get back the order and the basket. but the entity $basket->getDeclinations() does not have any thing

What I am doing wrong?

like image 863
user1014102 Avatar asked Nov 04 '22 05:11

user1014102


2 Answers

If the problem is indeed that the entity manager is not refreshing associations (as suggested by Mohammad AbuShady), the answer to tell your entities to cascade the refresh operation.

class Basket
{
    // ... 

    /**
     * @var array $declinations
     *
     * @ORM\OneToMany(
     *   targetEntity="Entity\BasketDeclination", 
     *   mappedBy="basket",
     *   cascade={"refresh"}    // THIS LINE ADDED
     * )
     */
    protected $declinations;

    // ...
...
}
like image 107
edan Avatar answered Nov 15 '22 08:11

edan


I will go with two guesses:

  • You should use the cascade annotation to the classes to allow cascade "persist" and probably cascade "refresh" too. As stated on the documentation. Something like:

    @ORM\OneToOne(targetEntity="Entity\Order", mappedBy="basket", cascade={"persist", "remove", "refresh"})

  • You are missing a persist() or a flush() on the Declinations before refreshing. If you are not cascading you need to call them on each object you want to keep and THEN call the refresh() method.

(It's always a good idea too to check that your proxies are created and working all right when you work with nested objects)

like image 32
Hiraqui Avatar answered Nov 15 '22 08:11

Hiraqui