2016-06-08 12 views
3

Bevor ich beginne, beachte, dass ich Symfony lerne, also denke daran! Ich möchte nur verstehen, wie es funktioniert. Hier ist, was ich zu erreichen versuche:Symfony 2.8+, Dokumentinsertion und Formulare

Ich möchte ein funktionierendes Crud Beispiel der Entitäten Vererbung mit Lehre. Das ist also, wie mein Beispiel wie folgt aussieht:

  • Zusammenfassung Übergeordnete Klasse: Charakter
  • Kinderklasse 1: Magier
  • Kinderklasse 2: Krieger
  • Kinder Klasse 3: Archer

So Nachdem ich einige Dokumente gelesen hatte, entschied ich mich, die STI (Single Table Inheritance) von Doctrine zu verwenden.

Übergeordnete Klasse:

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

Kinder Klasse 1:

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

Kinder Klasse 2:

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

Kinder Klasse 3:

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

ich den Tisch in meinem db erstellen verwaltet, und ich erfolgreich geladen meine Vorrichtungen für Tests Zwecke. Ich habe auch meine Hauptansicht funktionieren lassen (alle Charaktere auflisten).


Mein Problem: Jetzt mag ich in der Lage sein, zu erstellen, bearbeiten & mit einem einzigen Formular ein bestimmtes Zeichen in der Liste löschen. So würde ich zum Beispiel ein "Typ" auswählen Feld, wo ich "Krieger", "Zauberer" oder "Bogenschütze" auswählen und dann in der Lage sein würde, die spezifischen Felder der gewählten Entität auszufüllen. Also lass uns sagen, ich wähle "Krieger" in der Form, dann würde ich gerne in der Lage sein, die Rüstung Eigenschaft (zusammen mit den Eltern natürlich) und behalte es in der Datenbank.

Ich weiß nicht, wie es geht, da meine Elternklasse abstrakt ist, so dass ich kein Formular basierend auf diesem Objekt erstellen kann.

Danke im Voraus für Ihre Hilfe, ich brauche es wirklich!

PS: Wenn es eine bessere Lösung/Implementierung gibt, zögern Sie nicht!

Antwort

1

Der einfachste Weg besteht darin, alle Felder anzugeben und sie nach dem Wert 'type' zu entfernen.

Dazu müssen Sie die Logik auf der Client-Seite (für die Anzeige Zweck) und Server-Seite (damit die entfernten Felder können nicht in Ihrer Entität geändert werden) zu implementieren.

Auf der Clientseite:

  • Verwenden Sie Javascript um die Arten zu verstecken, die für jeden ‚Typ‘ ändern können nicht gesetzt ist (Sie können JQuery verwenden und die .Hide() Funktion).

Auf der Serverseite:

  • einen PRE_BIND Termin in Ihrem Formulartyp, Fügen Sie die Felder aus der Form zu entfernen:

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

sollte Ihr Formular aussehen wie:

// ... 

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

// ... 

EDIT

mit Single Table Inheritance umgehen, können Sie nicht eine abstrakte Klasse verwenden, muss die Basisklasse eine normale Person sein. Geben Sie in Ihrem Formular einfach die Klasse AppBundle \ Character ein.

In Ihrem Controller-Aktion, die den Charakter erstellt, müssen Sie Ihr Unternehmen mit so etwas wie dies initiieren:

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

Durch die Bearbeitung und den Charakter zu entfernen, können Sie direkt mit dem Character Entity beschäftigen.

Ich empfehle der Benutzer die Art nicht zu lassen, indem bearbeiten ändern, für die Beantwortung Doctrine: Update discriminator for SINGLE_TABLE Inheritance

+0

Dank sehen, ich verstehe immer noch nicht, wie ich den generischen Formulartyp alle Felder enthält, schaffen würde und nennt es dann in meinem Controller. – Elbarto

+0

Wie alle anderen generischen formTypes. Sie können es direkt im Controller erstellen (wie in meinem Beispiel) oder es in einer separaten formType-Klasse speichern. Es muss jedoch den Block "addEventListener" enthalten, um Ihr Problem zu lösen. Ich werde Ihnen kein Tutorial über Forms machen. Das ist nicht deine Frage. Alles ist hier: http://symfony.com/doc/current/book/forms.html – Alsatian

+0

Sorry, ich drückte auf Enter, ich konnte meinen vorherigen Kommentar für einige mns nicht bearbeiten. Was ich sagen wollte ist: ist keine Form, die auf einer Entität basieren soll? Weil ich einen formType namens CharacterType erstellt habe. Aber dann in meinem Controller, da meine Zeichenklasse abstrakt ist, kann ich das nicht tun: $ char = new Character() und dann $ form = $ this-> createForm (CharacterType :: class, $ char); Ich lerne immer noch, vielleicht habe ich die Formen nicht gut genug verstanden. – Elbarto