Ankündigung

Einklappen
Keine Ankündigung bisher.

Form-Objekt mit Form-Elementen aus Daten-Objekt anreichen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Form-Objekt mit Form-Elementen aus Daten-Objekt anreichen

    Hallo zusammen,

    ich habe etwa folgende Situation...
    Ich habe ein Form-Objekt, bei dem ich über register() Form-Elemente registrieren kann.
    Und ich habe Datenobjekte, die in eine Datenbanktabellenzeile repräsentieren und in denen grundsätzlich auch genug Infos hinterlegt sind, um daraus ein passenden Form-Element zu erzeugen:
    PHP-Code:
    // Form::register(FormElement $element)
    $form = new Form('form_identifier');
    $form->register(new InputField('...'));
    $obj = new SomeDataObject();
    // und die die magische Zeile... 
    Naja, und jetzt suche ich nach einer Best Practise Lösung für ein solch artiges Problem. Ich habe hier neben mir Head First Design Patterns liegen und mal durchgeblättert. Ich möchte hier nicht auf Teufel komm raus irgendein Pattern anwenden, aber ich habe mir gedacht, dass es für sowas doch sicher schon einen guten Weg gibt.
    Die Pattern, bei denen ich Länger als eine Sekunde überlegt habe, waren das Adapter-Pattern, aber ich möchte ja das Daten-Objekt nicht wie ein Form aussehen lassen. Das Decorator-Pattern würde ja zum Form-Objekt zusätzliche Funktionalität hinzufügen, aber ich möchte ja nicht Funktionalität dranhängen, sondern quasi Daten. Joa, und der Rest ist eigentlich sofort ausgeschieden.
    Dann habe ich mal selbst meinen Kopf angestrengt, wie man das am Besten angeht.
    Eine Methode a la addElementsFromDataObject() am Form-Objekt wäre mMn nicht gut, da dann ja das Form-Objekt weiss, welche Objekte es hat - aktuell weiss es ja nur, dass es FormElement-Objekte hat.
    Ich habe noch an ein Translator-Klasse gedacht, die das Form-Objekt und das Daten-Objekt übergeben bekommt, und dann am Form-Objekt die Form Elemente anhängt, aber irgendwie bin ich davon auch noch nicht überzeugt.
    Die letzte Idee war am Daten-Objekt eine Methode hinzuzufügen, die ein Array (oder ein Collection-Objekt mit Objekte, Stilfrage, oder?) mit den entsprechenden FormElement-Objekten erzeugt und zurückgibt. Danach entweder über eine Schleife am Form registriert werden oder mit einer registerFromArray()-Methode

    Wie würdet ihr das angehen, damit die Objekte nicht mehr wissen, als sie wissen müssen.

    Danke und viele Grüße!


  • #2
    SOrry, aber was genau DU willst, hast Du noch nicht beschrieben.
    --

    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


    --

    Kommentar


    • #3
      Ok, sorry, ich versuch nochmal nachzulegen...
      Zitat von Lenki Beitrag anzeigen
      Naja, und jetzt suche ich nach einer Best Practise Lösung für ein solch artiges Problem.
      Das Problem, bzw. ehr die Fragestellung ist im Wesentlichen, wen ich sinnvoller weise die FormElement-Objekte erzeugen lasse: Also entweder das Daten-Objekt, das Form-Objekt oder eine Art Übersetzer-Objekt.
      Ich habe ja oben schon für die eine und die andere Lösung "argumentiert" und tendiere gerade zum Übersetzer-Objekt.
      Habe ich hier irgendetwas übersehen, einen Aspekt vergessen?

      Kommentar


      • #4
        Meiner Ansicht nach krankt der Ansatz an der Trennung der Zuständigkeiten. Für mich sollte Präsentation eines Formulars und die Logik getrennt werden. Initialisierung eines Formulars sollte man entweder durch "intelligente" Formular-Elemente realisieren, die ein Bindung zur Datenquelle injiziert bekommen oder von aussen - z.B. per MVC-Controller - steuern. Letzteres ist einfacher, da generischer umzusetzen.

        Beide Varianten erfordern jedoch eine bessere Abstraktion deines Formular-Objekts, denn so wie ich das Interface wahrnehme, lässt die Möglichkeit der Formatierung zu wünschen übrig.
        Viele Grüße,
        Dr.E.

        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        1. Think about software design before you start to write code!
        2. Discuss and review it together with experts!
        3. Choose good tools (-> Adventure PHP Framework (APF))!
        4. Write clean and reusable software only!
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        Kommentar


        • #5
          Schau dir doch mal z.b. sfForm (Symfony 1.4) oder Zend_Form (Zend Framework) an, beide arbeiten mit Dekoratoren die sich austauschen lassen.

          Dabei gibt es dann einen Dekorator für die Form und welche für jedes Element.
          Der Dekorator der Form bestimmt dann "die Umgebung" des Formulars, ob das ne Tabelle, ne Liste oder sonstwas ist.
          Die der Felder dann wie das Feld angelegt wird, wo die potentiellen Fehlermeldungen der Validierung positioniert werden, ... .

          Rein theorhetisch lässt sich das also auch umschreiben dass damit ein PDF-Formular oder rein theoerhetisch mit gdlib/imagemagick ein Bild erstellt wird
          robo47.net - Blog, Codeschnipsel und mehr
          | Caching-Klassen und Opcode Caches in php | Robo47 Components - PHP Library extending Zend Framework

          Kommentar


          • #6
            Ein Decorator klingt schon ganz sinnvoll. Du darfst nicht vergessen, dass Datentypen durchau mit mehreren Formelementen dargetellt werden können - z.B. mit Selections oder Radioboxes, mit Multi-Selects oder Checkboxgruppen...

            Im Endeffekt wäre das eine Möglichkeit:
            PHP-Code:
            FF = new FormFactory;
            Form = new Form;

            while (
            set fetch_DB) {
              
            Form->addElement (FF->create (set Form));

            wobei FF->create () ein Formelement erzeugt und diesen mit einem Formelement-Decorator dekoriert zurückgibt.
            --

            „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
            Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


            --

            Kommentar


            • #7
              Zitat von dr.e. Beitrag anzeigen
              Meiner Ansicht nach krankt der Ansatz an der Trennung der Zuständigkeiten. Für mich sollte Präsentation eines Formulars und die Logik getrennt werden.
              Wo siehst du denn bei meinem Ansatz eine Vermischung von beidem? Wie das Formular angezeigt wird, ist hier noch nicht festgelegt. Oder findest du hier das InputField-Objekt zu einengend? Habe hier auch schon mit dem Gedanken gespielt, die Methode als eine Art FormElement-Factory zu verwenden und einfach nur einen String mit der Info zum Form-Element zu übergeben und den Rest der Factory zu überlassen (ähnlich, wie es bei Zend_Form möglich ist)
              Zitat von dr.e. Beitrag anzeigen
              Initialisierung eines Formulars sollte man entweder durch "intelligente" Formular-Elemente realisieren, die ein Bindung zur Datenquelle injiziert bekommen oder von aussen - z.B. per MVC-Controller - steuern. Letzteres ist einfacher, da generischer umzusetzen.
              Wenn ich das richtig verstehe, ist genau das meine Frage. Also doch eine Art Mittler-Objekt?
              Zitat von dr.e. Beitrag anzeigen
              Beide Varianten erfordern jedoch eine bessere Abstraktion deines Formular-Objekts, denn so wie ich das Interface wahrnehme, lässt die Möglichkeit der Formatierung zu wünschen übrig.
              Auf welche Ebene würdest du denn das ganze abstrahieren? Ich kann vom Grundgedanken her keinen Unterschied von meiner Abstraktion zu der von Zend_Form erkennen.

              Zitat von robo47 Beitrag anzeigen
              Dabei gibt es dann einen Dekorator für die Form und welche für jedes Element.
              Der Dekorator der Form bestimmt dann "die Umgebung" des Formulars, ob das ne Tabelle, ne Liste oder sonstwas ist.
              Mh, daran habe ich auch schon gedacht. Das möchte ich mir grundsätzlich offen lassen, aber noch nicht implementieren. Wenn ich Dekoratoren richtig verstanden habe, kann man sie doch eh immer "vorne drauf setzen" (aufs Form-Objekt und dadurch neue Funktionalitäten hinzufügen) Nichtsdestodrotz weiss das Formular-Objekt ja vorher schon (vor dem Dekorator), wieviele FormElemente es beinhaltet und mit welchen Datne sie gefüllt sind, nur nicht, wie diese FormElemente dann letzten Endes dargestellt werden, oder?

              Zitat von nikosch Beitrag anzeigen
              Ein Decorator klingt schon ganz sinnvoll. Du darfst nicht vergessen, dass Datentypen durchau mit mehreren Formelementen dargetellt werden können - z.B. mit Selections oder Radioboxes, mit Multi-Selects oder Checkboxgruppen...

              Im Endeffekt wäre das eine Möglichkeit:
              PHP-Code:
              FF = new FormFactory;
              Form = new Form;

              while (
              set fetch_DB) {
                
              Form->addElement (FF->create (set Form));

              wobei FF->create () ein Formelement erzeugt und diesen mit einem Formelement-Decorator dekoriert zurückgibt.
              Ok... hier wäre der Decorator dann aber "auf" dem Objekt, dass eine bestimmten Teil meines Datenobjektes (wenn das Datenobjekt eine Tabellenzeile wäre, also auf dem Objekt, dass die Tabellenzelle repräsentiert) repräsentiert, oder?
              Der Ansatz gefällt mir...

              Kommentar


              • #8
                Eigentlich nicht. Du schreibst oben, die DB-Datensätze enthalten genug Informationen um zu bestimmen, welcher Elementtyp sinnvoll ist. Aus der Übergabe von set (==Datensatz) oben würde die Factory
                1) diese Information auswerten
                2) einen passenden Elementtyp erstellen
                3) einen Decorator für diesen Elementtyp mit einem gegebenen Feldwert/Auswahlwert aus set erstellen.
                4) diesen Decorator den Form zuordnen

                Ich habe ähnliches schon versucht, deshalb sei hier gleich auf die Problematiken für Gruppenelemente hingewiesen:
                Aus Objektsicht haben gruppierte Elemente eine andere Struktur, sie sind quasi zweidimensional. Das „beißt“ sich aber mit relationalen Datenbanken, die jeden Wert quasi-atomar liefern. Damit musst DU
                1) Elementgruppen als komponiertes Objekt erstellen (außen Gruppe, innen Item-Objekte)
                2) Diese Objekte in der Factory vorhalten (von create zu create wird ja u.U. das gleiche Gruppenobjekt bestückt).
                Warum man die Elemente nicht einzeln behandeln kann:
                1) spätestens bei Selections mit der HTML-seitigen Schachtelung wird das klar (aber auch bei gut gemachten Radio-Gruppen, die bspw. durch fieldset gruppiert sind)
                2) die Zuordnung eines Vorgabe/Returnwertes muss ja irgebndwie zentral erfolgen (i.A. an ein Objekt, das durch das html-seitige name-Attribut repräsentiert wird). Damit nþzen Dir Einzelobjekte bspw. für <option> nicyt viel.

                Ein Ausweg - IMHO aber kein eleganter - könnte sein, die Factoryprodukte alle in ein Array zu schreiben und nachträglich auf Grundlage des name-Members zu gruppieren. Hierbei muss man dann natürlich Spezialitäten wie name[1], name[47] berücksichtigen...

                Ok... hier wäre der Decorator dann aber "auf" dem Objekt, dass eine bestimmten Teil meines Datenobjektes (wenn das Datenobjekt eine Tabellenzeile wäre, also auf dem Objekt, dass die Tabellenzelle repräsentiert) repräsentiert, oder?
                Nochmal kurz zurück zum Grundproblem. Das Problem an der ganzen Sache ist, dass Du auf beiden Seiten (Dateneingabe vs. Datendarstellung) verschiedene Datentypen hast - eindimensionale und mehrdimensionale. Das abzubilden ist enorm schwierig, weil Du auf keine Seite eine einheitliche Schnittstelle hinbekommst, auf der das andere Objekt aufbauen kann.
                --

                „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                --

                Kommentar


                • #9
                  Hallo Lenki,

                  nach Nikosch' Post muss ich denke ich nicht mehr im Datail auf deinen Post eingehen. Er hat sehr treffend beschrieben wo die Tücken einer derartigen Vorgehsweise liegen. Deshalb propagiere ich einen anderen Ansatz als beispielsweise Zend_Form: ein Formular ist auch nichts anderes als ein Template mit "Formular-sensitiven" Elementen, die durch die Tag-Struktur nach der Analyse als echte Objekt-Struktur zur Verfügung steht. Dadurch hast du sowohl die Möglichkeit, die Elemente sehr einfach zu formatieren und zu platzieren als auch eine saubere Objekt-Struktur, die du entsprechend adressieren, befüllen und manipulieren kannst.

                  Den Overhead mit Decoratoren und Gruppierungs-Elementen nimmt dir immer Flexibilität, die spätestens bei komplexeren Aufgaben notwendig ist.
                  Viele Grüße,
                  Dr.E.

                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  1. Think about software design before you start to write code!
                  2. Discuss and review it together with experts!
                  3. Choose good tools (-> Adventure PHP Framework (APF))!
                  4. Write clean and reusable software only!
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  Kommentar


                  • #10
                    Es spricht ja nichts gegen eine Vermischung. Bei Bedarf nutzt man dann entweder einen Decorator zur Ausgabe oder schreibt eben plain html..

                    Kommentar


                    • #11
                      Naja, ob bspw. die Factory ein Objekt dekoriert sollte man schon klären.
                      --

                      „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                      Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                      --

                      Kommentar


                      • #12
                        Zitat von xm22 Beitrag anzeigen
                        Es spricht ja nichts gegen eine Vermischung. Bei Bedarf nutzt man dann entweder einen Decorator zur Ausgabe oder schreibt eben plain html..
                        Plain HTML ist Blödsinn, da verzichtest du auf wichtige Features und programmierst diese mit Unmengen Template-Logik nach. Das hat weder etwas mit OO zu tun, noch ist das in nicht-Hobby-Projekten rentabel.
                        Viele Grüße,
                        Dr.E.

                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                        1. Think about software design before you start to write code!
                        2. Discuss and review it together with experts!
                        3. Choose good tools (-> Adventure PHP Framework (APF))!
                        4. Write clean and reusable software only!
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                        Kommentar


                        • #13
                          Plain HTML ist Blödsinn
                          Was ist daran bitte Blödsinn?! Hast Du schon mal ein Formular gehabt, dass auf diverse JS-Effekte wie Ajax-Hints und ähnliches zurück gegriffen hat? Oder auf eine spezielle Art und Weise gestaltet werden sollte?
                          Das, was das APF hier anbietet: Kontaktformular-Tutorial :: Adventure PHP Framework (APF)
                          Ist doch im Prinzip nichts weiter als die Validierung und Ausgabe des Formulars in einem Stück Code.. Da könnte man auch das Formular als eigenes Objekt mit allen Validierungen und was dazu gehört, instanziieren und die HTML-Ausgabe per Hand schreiben. Bei der Ausgabe gäbe es kaum einen Unterschied zu Deiner Lösung, außer, dass Du alles in spezielle Tags verpackst, die noch etwas Arbeit abnehmen..

                          Kommentar


                          • #14
                            Hallo zusammen,

                            es ist schon ein wenig her...

                            Ich muss gestehen, ich hatte die letzten Diskussionen nicht ganz folgen können, hatte dann aber einen, meiner Meinung nach, grandiosen Einfall, den ich dann unbedingt mal umsetzen wollte. Den möchte ich hier mal kurz skizzieren:
                            PHP-Code:
                            $form Form::getInstance('id');
                            if(!
                            $form->hasElements()) { // Form wurde neu erzeugt, nicht aus Session
                              
                            $do = new PersonDataObject(3); // Holt das Personen-Objekt mit ID 3 mit Vor- und Nachname aus der Datenbank
                              
                            $provider = new DataObjectFormElementProvider($do); // Klasse, die Form Elemente aus dem Daten-Objekt bereitstellt
                              
                            $form->registerElementsFromProvider($provider);
                            }
                            if(
                            $form->submitted()) {
                              if(!
                            $form->valid()) {
                                
                            $errors $form->getErrors();
                                
                            // Errors weiterverarbeiten
                              
                            } else {
                                new 
                            SaveDataObjectFormDecorator($form)->save();
                                
                            // ok, der Teil ist noch wirklich nicht gut modeliert, ich weiß
                              
                            }

                            Die Form-Instanz würde an den View übergeben werden. Dort würden die Form Elemente mit einem HTML Form Element Decorator bestückt, der daraus ein HTML Element erzeugen kann.
                            Funktioniert soweit wunderbar (auch wenn der letzte Teil mit dem Speichern noch nicht schön ist...)

                            Da war ich echt begeistert und hab mir gedacht: Jetzt bearbeite mal zwei Personen-Datensätze in einem Formular. Und da war es dann: PENG!!!

                            Ich hätte dann zwei Form-Elemente mit dem HTML-Name-Attribute <form_prefix>_vorname und <form_prefix>_nachname. Doof gelaufen.

                            Und ich glaube, das ist genau das, wovor ihr gewarnt habt, oder?
                            Jetzt bin ich hier am Grübeln.
                            Mein aktueller Ansatz ist in etwa folgender: Ich bilde meine Form-Elemente in einer Art Baum ab. Jedes Form-Objekt hat von sich aus einen Root-Knoten. An diesem Knoten und potentiellen Kindknoten können Form-Elemente registriert werden. Knoten werden einfach über einen String wie ROOT/CHILD01/SUBCHILD02 angesprochen. Aber irgendwie ist das gnaze noch nicht so durchdacht. Ich habe einerseits den Ansatz versucht, wie ich das ganze in meinen Templates aufrufen wollen möchte. Hier hatte ich überlegt ein Pseudo-HTML Element einzufügen a la <node>, dass innerhalb eines <form>-Elements die darin angeforderten Elemente auf den angegebenen Knoten bezieht. Aber so wirklich habe ich auch noch nicht raus, wie ich zum Beispiel diese zwei Personen-Objekte dann angehe. Eigentlich wäre in diesem Ansatz jedes registrierte Daten-Objekt ein Knoten.
                            Es gäbe dann also eine Art Baum a la:
                            Code:
                            Root
                            + PersonData
                              + 3
                                - Nachname
                                - Vorname
                              + 5
                                - Nachname
                                - Vorname
                            + sind Knoten
                            - sind Attribute es Knoten
                            Hmm, aber so müsste ich sicherstellen, dass der Knoten PersonData nur die Unterknoten hat, die ein PersonDataObject abbilden. Hier wäre doch dann wieder das Problem, dass die Form-Elemente nicht wissen, dass sie an ein Daten-Objekt gebunden sind.

                            Hm, also das ganze muss auf jeden Fall noch reifen.
                            Würde mich freuen, wenn ihr Eure Meinung dazu gebt.
                            Dankeschön.

                            Kommentar


                            • #15
                              Hallo Lenki,

                              die Diskussion ging vor deinem Post genu um das Thema Abstraktion und Abbildung von komplexeren Strukturen. Richtig ungemütlich wird es bei Multi-Selekt-Felder mit Gruppen. Hier muss der Provider eine Hierarchie von Daten verwalten und der Decorator auch speichern können. Letzterer ist eigentlich kein Decorator, denn ein solcher ist zur Präsentation eines Objekts gedacht, nicht zur Persistenz.

                              Auch die Verarbeitung von Validierungs-Fehlern und Filter-Mechanismen von Formular-Elementen zusammen mit einer generischen Datenquelle ist nicht besonders handlich zu implementieren. Ich verfechte deshalb den Ansatz des APF, dass ein Formular nichts anderes als ein Template bestehend aus Funktions-sensiblen Tags ist, die für dich Filterung, Presetting, Validierung etc. übernehmen und ebenfalls als Datenquelle und -Senke fungieren können. Die letzten beiden Aspekte sind im MVC-Pattern IMHO jedoch Aufgabe eines Controllers, der eine Formular-Repräsentation in ein Domänen-Objekt oder Model transfomiert und zur Persistenz bzw. weiteren Verarbeitung freigibt.

                              Weiterer Vorteil des Ansatzes des APF ist, dass die Formatierung nicht umständlich und sogar krankhaft mit Dekoratoren o.ä. implementiert werden muss, sondern es reicht, ein Formular-Feld in einem Formular zu platzieren und per CSS zu formatieren. Bei komplexeren Formularen kann dieses auch ganz einfach dynamisch erzeugt werden, sprich es ist mit demselben Konzept möglich, Formulare zur Laufzeit im Controller zu generieren und zu verarbeiten. Alle diese Funktionen hat das APF-Form-Tag schon an Board.

                              Ich leg dir deshalb ans Herz, dir die Umsetzung der Formular-Integration unter Formulare (ab Version 1.11) :: Adventure PHP Framework (APF) einmal durchzulesen und das für deinen Anwendungsfall durchzuspielen. Ich bin sicher, das ist deutlich einfacher zu handhaben und viel einfacher zu skalieren als der von dir gedachte Ansatz.
                              Viele Grüße,
                              Dr.E.

                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                              1. Think about software design before you start to write code!
                              2. Discuss and review it together with experts!
                              3. Choose good tools (-> Adventure PHP Framework (APF))!
                              4. Write clean and reusable software only!
                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                              Kommentar

                              Lädt...
                              X