я имею 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
}
}
]
}
это работает нормально, но это не то, что я хочу сделать 🙁 Я подозреваю, что решение может заключаться в том, чтобы каким-то образом изменить порядок сохранения сущностей. Если сообщение было сохранено первым, а категория — вторым, это должно сработать.
Как правильно сохранить эту ассоциацию?
Не знаю, актуально ли это для вас, но решение довольно простое.
Вы должны настроить 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;
}
Других решений пока нет …