Вопрос по serialization, doctrine-orm, symfony, deserialization – Как управлять десериализованными сущностями с помощью менеджера сущностей?

2

Я использую JMSSerializerBundle для сериализации своих сущностей для json и десериализации json в сущности, но я думаю, что этот вопрос применим для любых методов десериализации.

Например, эта схема:

class Order
{
    private $id;

    /**
     * @Serializer\Type("ArrayCollection<MyBundle\Entity\Order\Item>")
     * @ORM\OneToMany(targetEntity="\MyBundle\Entity\Order\Item", mappedBy="order", cascade={"persist"})
     */
    private $items;
}

class Item
{

    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="\MyBundle\Entity\Order", inversedBy="items")
     */
    private $order;

    /**
     * @var integer $amount
     * @Serializer\Type("integer")
     * @ORM\Column(name="amount", type="integer")
     */
    private $amount;

}

Карты к этому JSON:{"id":1,"items":[{"id":1,"amount":100}, {"id":2,"amount":200}]} и тот же самый JSON должным образом десериализован в объект типаMyBundle:Order у которого есть коллекция из двухMyBundle:Order/Item объекты.

Проблема в том, что когда я пытаюсь сохранить этот объект, в базе данных создаются новые записи, а не обновляются существующие, игнорируя идентификаторы. Как мне сказать менеджеру сущностей, что эти объекты должны быть обновлены, а не созданы?

Update, В общем, решение EntityManager :: merge (как предлагает DaveM) - это хорошо. Но вы должны только объединить существующие объекты. Например, если у вас есть json, который представляет новую сущность Order, связанную с существующими сущностями Order \ Item

{"id":null,"items":[{"id":1,"amount":100}, {"id":2,"amount":200}]}

В этом случае вы не можете просто объединить объект Order следующим образом: $em->merge($order)потому что order - это новая сущность, а менеджер сущностей попытается найти объект Order с id = null, и вы получите новый Order и массив пустых элементов. Поэтому решение состоит в том, чтобы зациклить массив Order :: $ items и объединить каждый элемент по отдельности. Затем будет создан новый заказ и связан с существующими элементами.

Ваш Ответ

2   ответа
2

что этому вопросу уже три года, но меня вводит в заблуждение мысль, что единственным ответом было использование операции слияния. Я хотел бы добавить свои два цента:

JMSSerializerBundle включает в себя конструктор объектов для сущностей Doctrine. Когда вы включаете этот конструктор, десериализованные сущности являются управляемыми сущностями, которые могут быть сохранены (с$em->persist($entity)).

пожалуйста, проверьтеэтот комментарий чтобы понять другие выгоды от этого. А такжеВот как вы можете включить его.

6

merge() метод наEntityManager под объединяющимися объектами понимается объединение объектов в контексте EntityManager, чтобы они могли снова стать управляемыми. Чтобы объединить состояние объекта в EntityManager, используйте метод EntityManager # merge ($ entity). Состояние переданной сущности будет объединено в управляемую копию этой сущности, и эта копия впоследствии будет возвращена.

$detachedEntity = unserialize($serializedEntity); 
$entity = $em->merge($detachedEntity);

Также обязательно обратите внимание, что когда вы хотите сериализовать / десериализовать сущности, вы должны сделать все свойства сущностей защищенными, а не частными. Причина этого заключается в том, что если вы сериализовали класс, который ранее был экземпляром прокси, закрытые переменные не будут сериализованы, а уведомление PHP будет выдано.

Более подробную информацию можно найти в документации доктрины здесь:

http://doctrine-orm.readthedocs.org/en/2.0.x/reference/working-with-objects.html#merging-entities

Похожие вопросы