Symfony 2.8+,学说继承和形式 [英] Symfony 2.8+, Doctrine Inheritance and Forms

查看:16
本文介绍了Symfony 2.8+,学说继承和形式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Before i start, Note that I'm learning symfony so keep that in mind ! I just want to understand how it works. Here's what i am trying to achieve :

我想用教义做一个实体继承的工作粗略示例.所以这就是我的例子的样子:

I would like to make a working crud example of entities inheritance using doctrine. So this is how my example looks like :

  • 抽象父类:字符
  • 儿童班 1:魔术师
  • 儿童 2 班:战士
  • 儿童 3 班:弓箭手

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

So after reading some documentation i decided to use the STI (Single Table Inheritance) of Doctrine.

父类:

/**
 * Character
 *
 * @ORMTable(name="character")
 * @ORMEntity(repositoryClass="AppBundleRepositoryCharacterRepository")
 * @ORMInheritanceType("SINGLE_TABLE")
 * @ORMDiscriminatorColumn(name="discr", type="string")
 * @ORMDiscriminatorMap({"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();
}

我设法在我的数据库中创建了表,并且我成功地加载了我的固定装置以进行测试.我还制作了我的主要视图(列出所有字符).

I managed to create the table in my db, and i successfully loaded my fixtures for tests purposes. I also made my main view work (listing all characters).

我的问题:现在我希望能够创建、编辑和使用单个表单删除列表中的特定字符.因此,例如,我将有一个 'type' 选择字段,我可以在其中选择 'warrior'、'magician' 或 'archer',然后我将能够填写所选实体的特定字段.因此,假设我在表单中选择战士",那么我希望能够设置 盔甲属性(当然还有父母之一)并将其保存在数据库中.

My Problem : Now i want to be able to create, edit & delete a specific character in the list with a single form. So for example i would have a 'type' select field where i can select 'warrior' , 'magician' or 'archer' and then i would be able to fill in the specific fields of the chosen entity. So let's say i choose 'warrior' in the form, then i would like to be able to set the armor property (along with the parents one of course) and persist it in the database.

我不知道该怎么做,因为我的父类是抽象的,所以我无法基于该对象创建表单.

I don't know how to do it since my parent class is abstract so i can't create a form based on that object.

提前感谢您的帮助,我真的需要它!

Thx in advance for your help, i really need it !

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

推荐答案

最简单的方法是提供所有字段并根据'type'值将其删除.

The easiest way is to provide all fields and to remove them according to the 'type' value.

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

To do that you have to implement the logic on the client side (for displaying purpose) and server side (so that the removed fields cannot be changed in your entity).

在客户端:

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

在服务器端:

  • 向您的表单类型添加 PRE_BIND 事件,以从表单中删除字段:

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

您的表单应如下所示:

// ...

use SymfonyComponentFormFormEvent;
use SymfonyComponentFormFormEvents;
use SymfonyComponentFormExtensionCoreTypeChoiceType;

$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();

// ...

编辑

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

To deal with Single Table Inheritance, you can't use an abstract class, the base class must be a normal entity.

在您的表单中,只需将类设置为 AppBundleCharacter.

In your form, just set the class as AppBundleCharacter.

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

In your controller action which creates the character, you must initiate your entity with something like this :

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();
}

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

By editing and removing the character, you can directly deal with the Character Entity.

我建议不要让用户通过编辑更改类型,请参阅 Doctrine: 更新 SINGLE_TABLE 继承的鉴别器

I recommand to not let the user change the type by edit, see Doctrine: Update discriminator for SINGLE_TABLE Inheritance

这篇关于Symfony 2.8+,学说继承和形式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆