Symfony 与api平台的嵌入关系
我怀疑的是Api平台。() 我有两个实体。问答。我想打一个电话来创建一个只有一个答案的问题。我展示我的实体Symfony 与api平台的嵌入关系,symfony,symfony4,api-platform.com,Symfony,Symfony4,Api Platform.com,我怀疑的是Api平台。() 我有两个实体。问答。我想打一个电话来创建一个只有一个答案的问题。我展示我的实体 namespace App\Entity; use ApiPlatform\Core\Annotation\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ApiResource(
* normalizationContext={"groups"={"question"}},
* denormalizationContext={"groups"={"question"}})
* @ORM\Entity
*/
class Question
{
/**
* @Groups({"question"})
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @Groups({"question"})
* @ORM\Column
* @Assert\NotBlank
*/
public $name = '';
/**
* @Groups({"question"})
* @ORM\OneToMany(targetEntity="Answer", mappedBy="question", cascade={"persist"})
*/
private $answers;
public function getAnswers()
{
return $this->answers;
}
public function setAnswers($answers): void
{
$this->answers = $answers;
}
public function __construct() {
$this->answers = new ArrayCollection();
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getId(): int
{
return $this->id;
}
}
和一个应答实体
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\Groups;
/**
*
* @ApiResource
* @ORM\Entity
*/
class Answer
{
/**
* @Groups({"question"})
* @ORM\Id
* @ORM\Column(type="guid")
*/
public $id;
/**
* @Groups({"question"})
* @ORM\Column
* @Assert\NotBlank
*/
public $name = '';
/**
* @ORM\ManyToOne(targetEntity="Question", inversedBy="answers")
* @ORM\JoinColumn(name="question_id", referencedColumnName="id")
*/
public $question;
public function getQuestion()
{
return $this->question;
}
public function setQuestion($question): void
{
$this->question = $question;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getId(): string
{
return $this->id;
}
public function __toString()
{
return $this->getName();
}
}
现在,我可以从nelmio的仪表盘中创建一个问题并将其转化为一个答案。但在数据库中,我的回答没有保存与问题的关系
{
"name": "my new question number 1",
"answers": [
{
"id": "ddb66b71-5523-4158-9aa3-2691cae9d473",
"name": "my answer 1 to question number 1"
}
]
}
另一个问题是。。。我已通过guid更改了我的答案id,因为当我将问题和答案创建为没有id的问题时,会出现错误。我是否可以创建问题和答案而不指定id
提前感谢第一点,它应该可以毫无问题地保存在数据库中。无论如何,您可以为问题实体创建一个PostValidateSubscriber,并检查该关系是否存在
<?php /** @noinspection PhpUnhandledExceptionInspection */
namespace App\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
final class QuestionPostValidateSubscriber implements EventSubscriberInterface
{
private $tokenStorage;
public function __construct(
TokenStorageInterface $tokenStorage
) {
$this->tokenStorage = $tokenStorage;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => ['checkQuestionData', EventPriorities::POST_VALIDATE]
];
}
/**
* @param GetResponseForControllerResultEvent $event
*/
public function checkQuestionData(GetResponseForControllerResultEvent $event)
{
$bid = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$question instanceof Question || (Request::METHOD_POST !== $method && Request::METHOD_PUT !== $method))
return;
$currentUser = $this->tokenStorage->getToken()->getUser();
if (!$currentUser instanceof User)
return;
}
}
我在你的实体中看到了一些错误。。。首先,由于问答实体之间的关系是一个单一实体,您的Qestion实体应该实现此功能,即:
use ApiPlatform\Core\Annotation\ApiProperty;
//..... the rest of your code
/**
* @ApiProperty(
* readableLink=true
* writableLink=true
* )
* @Groups({"question"})
* @ORM\OneToMany(targetEntity="Answer", mappedBy="question", cascade={"persist"})
*/
private $answers;
public function __construct()
{
//....
$this->answers = new ArrayCollection();
//...
}
public function addAnswer(Answer $answer): self
{
if (!$this->answers->contains($answer)) {
$this->answers[] = $answer;
$answer->setQuestion($this)
}
return $this;
}
public function removeAnswer(Answer $answer): self
{
if ($this->answers->contains($answer)) {
$this->answers->removeElement($answer);
}
return $this;
}
命令
PHP bin/console make:entity
允许您在关系类型的实体中创建字段,它为您创建这些方法,只需按照说明操作(创建两个实体后,使用命令更新问题实体…)
readableLink ApiProperty注释用于GET请求时查看嵌入对象,如果使用序列化组,则注释相同,如果将其设置为false,则响应如下所示:
{
"name": "my new question number 1",
"answers": [
"/api/answers/1",
"/api/answers/2",
....
]
}
它用于使响应更小(除其他外)。。。writableLink用于允许这样的POST请求(有关更多信息,请参见此示例):
当然,在每个实体中使用相应的序列化组。。。
在APIC平台中,嵌入式对象通过setters和getter方法持久化,但也可以为OneToMany关系添加和删除方法,剩下的工作由ORM完成。
让我知道这是否有帮助。干杯 答案正确保存,但答案数据库中的字段问题的值为NULL:/您找到解决方案了吗,我也有相同的问题。对象为persit,但关系id为Null。在这个问题上有什么进展?如果你有解决方案,请分享!
{
"name": "my new question number 1",
"answers": [
{
"id": "ddb66b71-5523-4158-9aa3-2691cae9d473",
"name": "my answer 1 to question number 1"
}
]
}