原则继承:更新实体字段

时间:2018-09-25 12:34:57

标签: symfony doctrine-orm doctrine symfony4

我正在尝试对某些API实体使用InheritanceType(“ JOINED”)。在尝试执行更新例程之前,一切似乎都能正常工作。

我有以下类:具有抽象子类ItemItemA等的抽象类ItemB。这些类具有子类SubItemASubItemB,依此类推。

根据实体的类,我需要能够更新不同的字段,因为并非所有子类都具有相同的字段。为此,我每个孩子班都有一个表格。这是我的功能:

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类中仅存在的字段保留到数据库中,这使我认为应将实体视为SubItemAItem

出于测试目的,我为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更改为非抽象,则所有内容均可以在第一个代码中正常运行。因此抽象的中间类似乎也发挥了作用...

0 个答案:

没有答案