我正在尝试对某些API实体使用InheritanceType(“ JOINED”)。在尝试执行更新例程之前,一切似乎都能正常工作。
我有以下类:具有抽象子类Item
,ItemA
等的抽象类ItemB
。这些类具有子类SubItemA
,SubItemB
,依此类推。
根据实体的类,我需要能够更新不同的字段,因为并非所有子类都具有相同的字段。为此,我每个孩子班都有一个表格。这是我的功能:
public function update(Request $request, $itemId): JsonResponse
{
$data = json_decode($request->getContent(), true);
$item = $this->entityManager->getRepository(Item::class)->findOneBy(['id' => $itemId]);
// ... Error Handling ...
// Get the form of the item child class
$itemType = get_class($item);
$formClass = null;
switch ($itemType) {
case 'SubItemA':
$formClass = SubItemAType::class;
break;
case 'SubItemB':
$formClass = SubItemBType::class;
break;
// ... Other Item Types ...
}
$form = $this->createForm($formClass, $item);
$form->submit($data);
// ... Error Handling ...
$this->entityManager->persist($item);
$this->entityManager->flush();
}
使用此功能时,我可以更新从Item
类继承的所有字段。但是,即使SubItemA
返回get_class($item)
,也只能将SubItemA
类中仅存在的字段保留到数据库中,这使我认为应将实体视为SubItemA
的Item
。
出于测试目的,我为SubItemA类创建了一个单独的存储库,并更改了getRepository
调用以获取该存储库:
public function update(Request $request, $itemId): JsonResponse
{
$data = json_decode($request->getContent(), true);
$item = $this->entityManager->getRepository(SubItemA::class)->findOneBy(['id' => $itemId]);
// ... Error Handling ...
// Get the form of the item child class
$itemType = get_class($item);
$formClass = null;
switch ($itemType) {
case 'SubItemA':
$formClass = SubItemAType::class;
break;
case 'SubItemB':
$formClass = SubItemBType::class;
break;
// ... Other Item Types ...
}
$form = $this->createForm($formClass, $item);
$form->submit($data);
// ... Error Handling ...
$this->entityManager->persist($item);
$this->entityManager->flush();
}
使用此代码,我可以更新实体的所有字段,即使是仅在SubItemA
类上定义的字段也是如此。但是当然,此代码不适用于SubItemB
类型的实体,依此类推。为了使我的所有子类型都能动态工作,我尝试了以下操作:
public function update(Request $request, $itemId): JsonResponse
{
$data = json_decode($request->getContent(), true);
$item_tmp = $this->entityManager->getRepository(Item::class)->findOneBy(['id' => $itemId]);
$item = $this->entityManager->getRepository(get_class($item_tmp))->findOneBy(['id' => $itemId]);
// ... Error Handling ...
// Get the form of the item child class
$itemType = get_class($item);
$formClass = null;
switch ($itemType) {
case 'SubItemA':
$formClass = SubItemAType::class;
break;
case 'SubItemB':
$formClass = SubItemBType::class;
break;
// ... Other Item Types ...
}
$form = $this->createForm($formClass, $item);
$form->submit($data);
// ... Error Handling ...
$this->entityManager->persist($item);
$this->entityManager->flush();
}
我意识到这段代码通过两次获取同一实体而引入了开销。但是可悲的是它甚至无法正常工作。同样,仅Item
类中的字段将被更新。似乎是在第一次加载实体后,它以某种方式被缓存并与Item
存储库相关联,从而阻止了我实际上通过我的SubItemA
存储库重新获取它。
我对Doctrine的内部运作方式还不了解,无法弄清楚这里发生了什么。推荐这样的更新方式是什么?我所有的子类都需要不同的API点吗?
修改
我刚刚发现,如果将“中间”抽象类ItemA
更改为非抽象,则所有内容均可以在第一个代码中正常运行。因此抽象的中间类似乎也发挥了作用...