Symfony 2.8+,主义继承和形式

时间:2016-06-08 08:37:25

标签: forms symfony inheritance doctrine entity

在我开始之前,请注意我正在学习symfony,所以请记住这一点!我只是想了解它是如何工作的。 这就是我想要实现的目标:

我想用doctrine做一个实体继承的工作示例。所以这就是我的例子:

  • 摘要父类:字符
  • 儿童班1:魔术师
  • 儿童班2:战士
  • 3级儿童: Archer

因此,在阅读了一些文档后,我决定使用Doctrine的STI(单表继承)。

家长班:

/**
 * Character
 *
 * @ORM\Table(name="character")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CharacterRepository")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({"magician_db" = "Magician", "warrior_db" = "Warrior", "archer_db" = "Archer"})
 */

abstract class Character{
    protected id;
    protected name;
    public function getId();
    public function getName();
    public function setName();
}

儿童等级1:

class Warrior extends Character{
       protected armor;
       public function battleShout();
}

儿童班2:

class Magician extends Character{
       protected silk;
       public function spellAnnounce();
}

儿童班3:

class Archer extends Character{
       protected leather;
       public function arrows();
}

我设法在我的数据库中创建表,并且我成功加载了我的灯具用于测试目的。我也使我的主视图工作(列出所有字符)。

我的问题: 现在我希望能够创建,编辑和使用单个表单删除列表中的特定字符。所以例如我会有一个'type'选择字段,我可以选择'warrior','magician'或'archer',然后我就可以填写所选实体的特定字段。所以,假设我在表单中选择“warrior”,然后我希望能够设置 armor property (当然还有父母)并将其保存在数据库中。

我不知道怎么做,因为我的父类是抽象的,所以我不能根据该对象创建一个表单。

提前帮助你,我真的需要它!

PS:如果有更好的解决方案/实施,请不要犹豫!

1 个答案:

答案 0 :(得分:1)

最简单的方法是提供所有字段,并根据'类型'删除它们。值。

为此,您必须在客户端(用于显示目的)和服务器端实现逻辑(以便在您的实体中无法更改已删除的字段)。

在客户端:

  • 使用javascript隐藏无法为每种类型设置的类型'更改(您可以使用JQuery和.hide()函数)。

在服务器端:

  • 将PRE_BIND事件添加到表单类型中,以从表单中删除字段:

http://symfony.com/doc/current/components/form/form_events.html#a-the-formevents-pre-submit-event

您的表格应如下所示:

// ...

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

$form = $formFactory->createBuilder()
    ->add('type', ChoiceType::class)
    ->add('armor')
    ->add('silk')
    ->add('leather')
    ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $submittedData = $event->getData();
        $form = $event->getForm();

        switch($submittedData['type'])
        {
            case 'warrior':
                $form->remove('silk');
                $form->remove('leather');
            break;
            case 'magician':
                $form->remove('armor');
                $form->remove('leather');
            break;
            case 'archer':
                $form->remove('armor');
                $form->remove('silk');
            break;
            default:
            throw new ...;
        }
    })
    ->getForm();

// ...

修改

要处理单表继承,您不能使用抽象类,基类必须是普通实体。

在表单中,只需将类设置为 AppBundle \ Character

在创建角色的控制器操作中,您必须使用以下内容启动实体:

if($request->isMethod('POST')){
    // form has been submitted
    switch($request->get('type'))
    {
        case 'warrior':
        $entity = new Warrior();
        ...
    }
}
else{
    // form has not been submitted, default : Warrior
    $entity = new Warrior();
}

通过编辑和删除角色,您可以直接处理角色实体。

我建议不要让用户通过编辑更改类型,请参阅Doctrine: Update discriminator for SINGLE_TABLE Inheritance