我对Api平台有疑问。 (https://api-platform.com) 我有两个实体。问题和答案。我想进行POST呼叫以创建一个答案的问题。我展示我的实体。
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吗?
预先感谢
答案 0 :(得分:0)
首先,它应该可以持久地存在数据库中。无论如何,您可以为Question实体创建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;
}
}
进行回显或使用xdebug进行检查。
第二点,您可以为实体的id添加这些注释,以便id可以自己生成。
答案 1 :(得分:0)
好吧,我看到您的实体中存在一些错误...首先,由于 Question 和 Answer 实体之间的关系是 OneToMany,您的 Qestion 实体应该实现此:
proc_1 = Process(target=my_func_1)
proc_2 = Process(target=my_func_2)
for proc in [proc_1, proc_2]:
proc.start()
# They are doing their thing and when they've completed they will join the
# main process and your main program can resume
for proc in [proc_1, proc_2]:
proc.join()
命令
import codecs, hashlib
pubkey = "AAAA...." #Put you public key string here
fingerprint = hashlib.md5(codecs.decode(bytes(pubkey,'utf-8'), 'base64')).hexdigest()
print(fingerprint)
允许您在关系类型的实体中创建一个字段,它会为您创建这些方法,只需按照说明操作(在创建两个实体后,使用命令更新问题实体...)
readableLink ApiProperty 注释用于查看 GET 请求上的嵌入对象,如果您使用序列化组,则相同,如果将其设置为 false,则响应将如下所示:
cs_fingerprint = ":".join([ fingerprint[pair:pair+2] for pair in range(0, len(fingerprint)-1, 2) ])
print(cs_fingerprint)
它用于使响应更小(除其他外)...而 writableLink 用于允许这样的 POST 请求(有关详细信息,请参阅此示例 here):
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;
}
当然,在每个实体中使用相应的序列化组... 在 ApiPlatform 中,嵌入的对象通过 setter 和 getter 方法持久化,但也为 OneToMany 关系添加和删除方法,其余的工作由 ORM 完成。 如果这有帮助,请告诉我。干杯!