API平台:规范化和取消规范化继承映射的学说实体

问题描述

我有一个称为Submission的实体类型。 SubmissionSurveyData实体类型具有OneToOne关系。

SurveyData实体实际上是一个映射的超类。最终,该实体将有几十个子类,用于存储来自不同调查的数据。

根据文档,我创建了一个自定义的Normalizer,用于基于type键处理反规范化:

  public function denormalize($data,string $type,string $format = null,array $context = [])
  {
    if ($type === 'App\Entity\SurveyData\SurveyData') {
      $class = 'App\Entity\SurveyData\\' . $data['type'];
      $context['resource_class'] = $class;
    }

    $context[self::ALREADY_CALLED] = true;

    return $this->denormalizer->denormalize($data,'App\Entity\SurveyData\\' . $data['type'],$format,$context);
  }

有了这个,我可以完美地创建一个带有嵌入式SurveyData的新提交。这是我发送给POST请求的JSON的示例:

{
    "facility": "/api/facilities/1","survey": "/api/surveys/monthly_totals","dateDetail": "Q1 2020","surveyData": {
      "type": "MonthlyTotals","num_deliveries": 50,"num_cesarean": 30,"num_epidural_anesthesia": 15
    },"created": "2020-08-14T18:59:49.218Z","updated": "2020-08-14T18:59:49.218Z","user": "brian","status": "complete"
}

但是,当我通过GET获取集合或单个提交实体时,API平台返回的响应忽略了将@id属性添加到嵌入式调查响应中。我不确定这是否是因为它是一个不能为空的OneToOne,所以它是内部跟踪的:

{
            "@id": "/api/submissions/2","@type": "Submission","id": 2,"facility": "/api/facilities/1","created": "2020-08-14T18:59:49+00:00","updated": "2020-08-14T18:59:49+00:00","status": "complete","surveyData": {
                "num_deliveries": 50,"num_epidural_anesthesia": 15
            }
        }

真正的问题PUTPATCH请求失败。

对于PATCH请求,我可以更新父提交实体中的字段。但是,如果我发送以下请求,则会从数据库中删除Submission和SurveyData实体,并且会从API中收到以下错误:

"Entity App\\Entity\\Submission@000000002116ebc30000000012ca4827 is not managed. An entity is managed if its fetched from the database or registered as new through EntityManager#persist",

要点包括整个响应,包括跟踪:https://gist.github.com/brianV/c32661186c91b49b013017dde77d5d4a

以下是触发错误的PATCH请求的示例:

{
    "user": "brian","surveyData": {
        "type": "MonthlyTotals","num_deliveries": 100
    }
}

这也发生在每个PUT请求中(其中包括整个替换Submission实体)。

在简单的Symfony&Doctrine中,此解决方案会很好用,但似乎破坏了API平台。

根据评论请求,以下是Submission实体注释:

/**
 * @ApiResource(
 *   normalizationContext={"groups"={"submission"}},*   denormalizationContext={"groups"={"submission"}},*   itemOperations={
 *     "get"={
 *       "method"="GET",*       "access_control"="is_granted('view',object)",*     },*     "put","patch","delete",*   },* )
 * @ORM\Entity(repositoryClass="App\Repository\SubmissionRepository")
 * @CustomAssert\SubmissionDataIsValid
 */
class Submission
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @Groups({"submission"})
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Facility")
     * @ORM\JoinColumn(nullable=false)
     * @Groups({"submission"})
     */
    private $facility;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Patient",inversedBy="submissions")
     * @Groups({"submission"})
     */
    private $patient;

    /**
     * @ORM\Column(type="string",length=255)
     * @Groups({"submission"})
     */
    private $survey;

    /**
     * @ORM\Column(type="string",length=255,nullable=true)
     * @Groups({"submission"})
     */
    private $dateDetail;

    /**
     * @ORM\Column(type="datetime")
     * @Assert\Type("\DateTimeInterface")
     * @Groups({"submission"})
     */
    private $created;

    /**
     * @ORM\Column(type="datetime")
     * @Assert\Type("\DateTimeInterface")
     * @Groups({"submission"})
     */
    private $updated;

    /**
     * @ORM\Column(type="string",length=255)
     * @Groups({"submission"})
     */
    private $user;

    /**
     * @ORM\Column(type="string",length=255)
     * @Groups({"submission"})
     */
    private $status;

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\SurveyData\SurveyData",inversedBy="submission",cascade={"persist","remove"},orphanRemoval=true,fetch="EAGER")
     * @Groups({"submission"})
     */
    private $surveyData;

在此先感谢您的帮助!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)