У меня есть две сущности, Вопрос и Альтернатива, где вопрос имеет отношение OneToMany с альтернативой, и я пытаюсь отправить JSON с вложенным документом Альтернатива через POST на платформу API Вопрос.
Платформа API возвращает эту ошибку ниже:
Nested documents for "alternatives" attribute are not allowed. Use IRIs instead.
Поискав об этом, я обнаружил, что некоторые люди говорят, что это возможно только с использованием IRI, а некоторые другие люди говорят, что для решения этой проблемы можно использовать контексты денормализации и нормализации, но я не могу найти пример или учебник по этому поводу.
TL;ДР;
Есть ли способ отправить вложенное отношение в сущность POST на платформе API без использования IRI?
Обновлено:
Как было задано, см. ниже два сопоставления сущностей «Вопрос» и «Альтернативный».
Вопрос
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass = "App\Repository\QuestionRepository")
* @ApiResource()
*/
class Question implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Token", inversedBy = "questions")
* @ORM\JoinColumn(nullable=false)
* @Assert\NotBlank()
*/
private $token;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Question", inversedBy = "question_versions")
*/
private $question;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\Question", mappedBy = "question")
*/
private $question_versions;
/**
* @ORM\Column(type = "integer")
* @Assert\NotBlank()
*/
private $version;
/**
* @ORM\Column(type = "string", length=100)
* @Assert\Length(max = "100")
* @Assert\NotBlank()
*
*/
private $name;
/**
* @ORM\Column(type = "integer")
* @Assert\NotBlank()
*/
private $type;
/**
* @ORM\Column(type = "text", length=65535)
* @Assert\NotBlank()
* @Assert\Length(max = "65535")
*/
private $enunciation;
/**
* @ORM\Column(type = "string", length=255, nullable=true)
* @Assert\Length(max = "255")
*/
private $material;
/**
* @ORM\Column(type = "text", length=65535, nullable=true)
* @Assert\Length(max = "65535")
*/
private $tags;
/**
* @ORM\Column(type = "boolean")
* @Assert\NotNull()
*/
private $public;
/**
* @ORM\Column(type = "boolean")
* @Assert\NotNull()
*/
private $enabled;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
*/
private $createdAt;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
*/
private $updatedAt;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\Alternative", mappedBy = "question")
*/
private $alternatives;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\QuestionProperty", mappedBy = "question")
*/
private $properties;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\QuestionAbility", mappedBy = "question")
*/
private $abilities;
/**
* @ORM\OneToMany(targetEntity = "QuestionCompetency", mappedBy = "question")
*/
private $competencies;
}
Альтернатива
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass = "App\Repository\AlternativeRepository")
* @ORM\Table(name = "alternatives")
* @ApiResource()
*/
class Alternative implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Question", inversedBy = "alternatives")
* @ORM\JoinColumn(nullable=false)
* @Assert\NotBlank()
*/
private $question;
/**
* @ORM\Column(type = "text", length=65535)
* @Assert\NotBlank()
* @Assert\Length(max = "65535")
*/
private $enunciation;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
*/
private $createdAt;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
*/
private $updatedAt;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\AlternativeProperty", mappedBy = "alternatives")
*/
private $properties;
}
@fyrye Я обновил вопрос, как вы и просили — Бруно де Соуза Роша только что Редактировать
Вы не используете группы сериализаторов или какие-либо другие контексты?
Нет, я использую только ресурс API
Это видео SymfonyCast показало мне, как именно решить эту проблему, используя аннотацию denormalizationContext! symfonycasts.com/screencast/api-platform/коллекции-создать






вы можете попробовать реализовать Денормализация
Вопрос:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass = "App\Repository\QuestionRepository")
* @ApiResource(
* denormalizationContext = {"groups" = {"post"}}
* )
*/
class Question implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Token", inversedBy = "questions")
* @ORM\JoinColumn(nullable=false)
* @Assert\NotBlank()
* @Groups({"post"})
*/
private $token;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Question", inversedBy = "question_versions")
* @Groups({"post"})
*/
private $question;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\Question", mappedBy = "question")
* @Groups({"post"})
*/
private $question_versions;
/**
* @ORM\Column(type = "integer")
* @Assert\NotBlank()
* @Groups({"post"})
*/
private $version;
/**
* @ORM\Column(type = "string", length=100)
* @Assert\Length(max = "100")
* @Assert\NotBlank()
* @Groups({"post"})
*/
private $name;
/**
* @ORM\Column(type = "integer")
* @Assert\NotBlank()
* @Groups({"post"})
*/
private $type;
/**
* @ORM\Column(type = "text", length=65535)
* @Assert\NotBlank()
* @Assert\Length(max = "65535")
* @Groups({"post"})
*/
private $enunciation;
/**
* @ORM\Column(type = "string", length=255, nullable=true)
* @Assert\Length(max = "255")
* @Groups({"post"})
*/
private $material;
/**
* @ORM\Column(type = "text", length=65535, nullable=true)
* @Assert\Length(max = "65535")
* @Groups({"post"})
*/
private $tags;
/**
* @ORM\Column(type = "boolean")
* @Assert\NotNull()
* @Groups({"post"})
*/
private $public;
/**
* @ORM\Column(type = "boolean")
* @Assert\NotNull()
* @Groups({"post"})
*/
private $enabled;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
* @Groups({"post"})
*/
private $createdAt;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
* @Groups({"post"})
*/
private $updatedAt;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\Alternative", mappedBy = "question")
* @Groups({"post"})
*/
private $alternatives;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\QuestionProperty", mappedBy = "question")
* @Groups({"post"})
*/
private $properties;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\QuestionAbility", mappedBy = "question")
* @Groups({"post"})
*/
private $abilities;
/**
* @ORM\OneToMany(targetEntity = "QuestionCompetency", mappedBy = "question")
* @Groups({"post"})
*/
private $competencies;
}
Альтернатива:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass = "App\Repository\AlternativeRepository")
* @ORM\Table(name = "alternatives")
* @ApiResource()
*/
class Alternative implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Question", inversedBy = "alternatives")
* @ORM\JoinColumn(nullable=false)
* @Assert\NotBlank()
* @Groups({"post"})
*/
private $question;
/**
* @ORM\Column(type = "text", length=65535)
* @Assert\NotBlank()
* @Assert\Length(max = "65535")
* @Groups({"post"})
*/
private $enunciation;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
* @Groups({"post"})
*/
private $createdAt;
/**
* @ORM\Column(type = "datetime")
* @Assert\DateTime()
* @Groups({"post"})
*/
private $updatedAt;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\AlternativeProperty", mappedBy = "alternatives")
* @Groups({"post"})
*/
private $properties;
}
Теперь вы можете отправить JSON в POST/PUT без IRI:
{
"token": "/api/tokens/1",
"question": "string",
"version": "string",
"name": "string",
"type": 0,
"enunciation": "string",
"public": true,
"enabled": true,
"alternatives": [
{
"enunciation": "String",
"createdAt": "2018-01-01 11:11:11",
"updatedAt": "2018-01-01 11:11:11"
}
]
}
было именно так! Вы спасли мой день. Большое спасибо.
Хороший ! это решение работает и со мной, спасибо
Для всех, у кого проблема с каскадом ошибок сохраняется, вы должны добавить его в свойство OneToMany. То есть для нашего вопроса:
@ORM\OneToMany(targetEntity = "App\Entity\Alternative", mappedBy = "question", cascade = {"persist"})
Обновите свой вопрос, включив в него сопоставления API-платформ двух объектов. Пример контекст сериализации см. в разделе api-platform.com/docs/core/serialization/….