我有一个名为提交
内容的实体类型。提交与
SurveyData
实体类型具有一对一关系。
SurveyData 实体实际上是一个映射的超类。它最终将有几十个用于存储来自不同调查数据的实体子类。
根据文档,我创建了一个自定义规范化器,它基于类型
键处理非规范化:
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
属性添加到嵌入式调查响应中。我不确定这是否是因为它是一个不能为空的一对一,所以它在内部被跟踪:
{
"@id": "/api/submissions/2",
"@type": "Submission",
"id": 2,
"facility": "/api/facilities/1",
"survey": "/api/surveys/monthly_totals",
"dateDetail": "Q1 2020",
"created": "2020-08-14T18:59:49+00:00",
"updated": "2020-08-14T18:59:49+00:00",
"user": "brian",
"status": "complete",
"surveyData": {
"num_deliveries": 50,
"num_cesarean": 30,
"num_epidural_anesthesia": 15
}
}
真正的问题是PUT
和PATCH
请求失败。
对于< code>PATCH请求,我可以更新父提交实体中的字段。但是,如果我发送以下请求,Submission和SurveyData实体将从数据库中删除,并且我会从API中得到以下错误:
“实体应用\\实体\\Submission@000000002116ebc30000000012ca4827不受管理。如果实体从数据库中获取或通过 EntityManager#persist 注册为新实体,则对其进行管理“,
整个反应的要点包括一个痕迹:https://gist.github.com/brianV/c32661186c91b49b013017dde77d5d4a
下面是一个触发错误的< code>PATCH请求的示例:
{
"user": "brian",
"surveyData": {
"type": "MonthlyTotals",
"num_deliveries": 100
}
}
每个PUT请求也会发生这种情况(其中我包括了整个替换提交实体)。
简单的Symfony
根据注释请求,以下是提交
实体注释:
/**
* @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;
提前感谢任何帮助!
确保使用api_platform.jsonld.normalizer对
服务。SurveyData
属性进行了规范化。当您使用提交
URL时,项目
我假设您已经按照这些步骤嵌入了您的对象?嗯,正如这里所描述的,因为你没有在你的嵌入对象中提供一个< code>@id属性,Api-Platform认为你在推一个新的对象,而不是编辑当前的对象,这就是为什么doctrine大叫(你的错误消息):这个新对象没有注册。
自动注册这个新对象的最简单方法是在提交::$调查数据
属性上添加层叠={"持续"}
注释属性:
class Submission
{
/**
* @OneToOne(targetEntity="App\Entity\SurveyData", cascade={"persist"})
*/
private $surveyData,
}
但您也可以使用EntityManagerInterface::persist()
方法。
注意:我不确定PATCH
方法是否与嵌入式对象完全兼容,我记得github上的一些问题。