symfony2 JMSSerializerBundle десериализует сущность с ассоциацией OneToMany

я имею Category OneToMany Post Ассоциация в doctrine2 настроена так:

Категория:

...
/**
* @ORM\OneToMany(targetEntity="Post", mappedBy="category")
* @Type("ArrayCollection<Platform\BlogBundle\Entity\Post>")
*/
protected $posts;
...

Сообщение:

...
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="posts")
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
* @Type("Platform\BlogBundle\Entity\Category")
*/
protected $category;
...

Я пытаюсь десериализовать следующий объект json (оба объекта с идентификатором 1 уже существуют в базе данных)

{
"id":1,
"title":"Category 1",
"posts":[
{
"id":1
}
]
}

используя метод десериализации сериализатора JMSSerializerBundle, настроенный с помощью конструктора объекта Doctrine

jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false

со следующим результатом:

Platform\BlogBundle\Entity\Category {#2309
#id: 1
#title: "Category 1"#posts: Doctrine\Common\Collections\ArrayCollection {#2314
-elements: array:1 [
0 => Platform\BlogBundle\Entity\Post {#2524
#id: 1
#title: "Post 1"#content: "post 1 content"#category: null
}
]
}
}

Что хорошо с первого взгляда. Проблема в том, что связанные Post имеет category поле установлено в null, в результате чего нет ассоциации на persist(), Если я попытаюсь десериализовать это:

{
"id":1,
"title":"Category 1",
"posts":[
{
"id":1
"category": {
"id":1
}
}
]
}

это работает нормально, но это не то, что я хочу сделать 🙁 Я подозреваю, что решение может заключаться в том, чтобы каким-то образом изменить порядок сохранения сущностей. Если сообщение было сохранено первым, а категория — вторым, это должно сработать.

Как правильно сохранить эту ассоциацию?

5

Решение

Не знаю, актуально ли это для вас, но решение довольно простое.

Вы должны настроить Accessor с установщиком для ассоциации, например:

/**
* @ORM\OneToMany(targetEntity="Post", mappedBy="category")
* @Type("ArrayCollection<Platform\BlogBundle\Entity\Post>")
* @Accessor(setter="setPosts")
*/
protected $posts;

Сериализатор вызовет метод установки для заполнения posts из JSON. Остальная логика должна быть обработана внутри setPosts:

public function setPosts($posts = null)
{
$posts = is_array($posts) ? new ArrayCollection($posts) : $posts;
// a post is the owning side of an association so you should ensure
// that its category will be nullified if it's not longer in a collection
foreach ($this->posts as $post) {
if (is_null($posts) || !$posts->contains($post) {
$post->setCategory(null);
}
}
// This is what you need to fix null inside the post.category association
if (!is_null($posts)) {
foreach ($posts as $post) {
$post->setCategory($this);
}
}

$this->posts = $posts;
}
0

Другие решения

Других решений пока нет …