turk porno porno escort rokettube
Seite 1 von 2 1 2 LetzteLetzte
Ergebnis 1 bis 20 von 29

Thema: Daten aus Doctrine Entity in Zend Form zu Verfügung stellen

  1. #1
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard Daten aus Doctrine Entity in Zend Form zu Verfügung stellen

    Hallo!

    Ich bin fleißig am rumbasteln mit Doctrine2 und habe Zend-Form direkt mit den Doctrine Entitäten verbunden. Ich arbeite also mit Entitäten, die in Fieldsets verwendet werden und die wiederrum in Formularen eingebunden werden (mit Hilfe des Hydrators).

    So kann ich Informationen direkt aus dem Formular speichern, ohne sie nochmal bearbeiten zu müssen. Auch Formulare, die weitere Entitäten enthalten sind kein Problem.

    ABER: Wie integriere ich in diese feste Struktur ein Formularfeld, dass mit bereits vorhandenen Daten einer Entität gefüttert werden soll (und deren Zusammenhänge das einfach in einer Referenztabelle gespeichert werden)?

    PHP-Code:
    class EntityFieldset extends Fieldset 
    {
        public function 
    __construct() {

            
    parent::__construct('book');
            
    $this->setHydrator(new \Zend\Stdlib\Hydrator\Reflection());
            
    $this->setObject(new \Article\Entity\Entity1());

            
    $this->add(array(
                   
    'name' => 'title',
                   
    'attributes' => array(
                          
    'type' => 'text',
                          
    'id' => 'title'
                   
    ),
                   
    'options' => array(
                          
    'id' => 'title',
                          
    'label' => 'Titelitel:',
                  )
            ));

            
    $this->add(array(
                   
    'type' => 'Zend\Form\Element\Select',
                   
    'name' => 'gender',
                   
    'options' => array(
                          
    'label' => 'gender',
                          
    'value_options' => array(
                                 
    '1' => 'Geschlecht',  
                                 
    '2' => 'Female',
                                 
    '3' => 'Male'
                         
    ),
                   ),
                   
    'attributes' => array(
                          
    'value' => '1' //set selected to '1' 
                   
    )
            ));

        }

    Wie interegriere ich bei dem zweiten $this->add eine weitere Entität, die einfach ihre Daten zur Verfügung stellt (anstelle von "Geschlecht, Female, Male") so, dass es anschließend auch als Objekt abgeleitet und die Abhängigkeiten automatisch mit in die Datenbank eingetragen werden?

    Lg,

    Powers
    Geändert von Powers (11.08.2013 um 16:49 Uhr)

  2. #2
    Super-Moderator Avatar von Kaiuwe
    Registriert seit
    30.12.2006
    Beiträge
    5.520
    Thanks
    4
    Thanked 356 Times in 287 Posts

    Standard

    Zitat Zitat von Powers Beitrag anzeigen
    Wie interegriere ich bei dem zweiten $this->add eine weitere Entität, die einfach ihre Daten zur Verfügung stellt (anstelle von "Geschlecht, Female, Male") so, dass es anschließend auch als Objekt abgeleitet und die Abhängigkeiten automatisch mit in die Datenbank eingetragen werden?
    Wenn ich dich richtig verstanden habe, dann sollte genau folgender Abschnitt in der Doku zum Ziel führen: „Zend\Form - Form Collections
    Zum Zend Framework stehen jedem folgende Quellen zum Nachschlagen zur Verfügung:

  3. #3
    Erfahrener Benutzer
    Registriert seit
    18.05.2012
    Beiträge
    156
    Thanks
    5
    Thanked 29 Times in 22 Posts

    Standard

    Schau dir mal DoctrineModule\Form\Element\ObjectSelect an. Ein Beispiel dazu findest du auf https://github.com/doctrine/Doctrine...orm-element.md

    Als Hydrator nutze ich DoctrineModule\Stdlib\Hydrator\DoctrineObject. Gerade einfache Sachen wie select-Elemente funktionieren da bei mir hervorragend

  4. The Following User Says Thank You to av3nger For This Useful Post:

    Powers (14.08.2013)

  5. #4
    Super-Moderator Avatar von Kaiuwe
    Registriert seit
    30.12.2006
    Beiträge
    5.520
    Thanks
    4
    Thanked 356 Times in 287 Posts

    Standard

    Zitat Zitat von av3nger Beitrag anzeigen
    Schau dir mal DoctrineModule\Form\Element\ObjectSelect an. Ein Beispiel dazu findest du auf https://github.com/doctrine/Doctrine...orm-element.md

    Als Hydrator nutze ich DoctrineModule\Stdlib\Hydrator\DoctrineObject. Gerade einfache Sachen wie select-Elemente funktionieren da bei mir hervorragend
    Die Frage ist, ob er nun die Auswahlliste mit Werten dynamisch befüllen möchte oder ob er die Werte aus der Auswahlliste auf ein weiteres Objekt „mappen“ möchte. Zumindest fand ich den letzten Satz dazu etwas unklar:
    Zitat Zitat von Powers
    Wie interegriere ich bei dem zweiten $this->add eine weitere Entität, die einfach ihre Daten zur Verfügung stellt (anstelle von "Geschlecht, Female, Male") so, dass es anschließend auch als Objekt abgeleitet und die Abhängigkeiten automatisch mit in die Datenbank eingetragen werden?
    Zum Zend Framework stehen jedem folgende Quellen zum Nachschlagen zur Verfügung:

  6. #5
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Hallo Kaiuwe, hallo ev3nger!

    Ich komme morgen erst wieder zum austesten, deswegen kam noch keine Antwort.

    Anwendung einfach beschrieben: Ich habe ein Formular, welches ich bin dem Doctrine Objekt "Buch" verbinde. Dieses Buch kann aber einen oder mehrere Autoren haben - und das ist die Frage der ich gerade nachgehe. Diese Autoren sind im vornherein angelegt und sollen beim Erstellen eines Buches dann zur Auswahl im Formular erscheinen (und anschließend natürlich mit abgespeichert werden).

    Ich hab derlei Kram auch schon im ZF1 mit Doctrine1 schon gemacht, jedoch noch auf ziemlich "handwerkliche" Art und Weise. Und wie ich das jetzt im ZF2 mit Doctrine2 und Form / Fieldsets / Hydrator so richtig schön zusammen einbinde - da bin ich noch im Lernmodus, auch wenns doch schon ganz gut klappt mittlerweile

    Das sieht schonmal sehr vielversprechend aus, danke für die Tips. Ich bin morgen wieder an der Sache dran.

  7. #6
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Soo, das sieht mittlerweile nun schon ganz gut aus. Ich kann ein Select Form erstellen, welches mit Daten aus der Datenbank (bzw. eines Doctrine-Objektes) gefüllt wird.

    Es war zuerst etwas kompliziert, weil ich immer wieder auf den Fehler "No object manager was set" gestossen bin. Im Netz bin ich dann auf Anleitungen getroffen, die in der Module.php die Formulare initialisieren und bereitstellen wollen. Ist aber alles quark, falls man es nicht gezielt so machen will.

    Zum Erfolg hat dieses Tutorial geführt. Es ist sehr kurz, simpel und so aufgebaut, dass es auf Anhieb funktioniert (zumindest bei mir):
    ZendFormElementSelect and Database Values - Sam minds

    Ich bin av3nger's Empfehlung gefolgt und habe im Abschnitt "Choose you method" die ObjectManager-Methode gewählt. Der Rest hat sehr gut geklappt und ich habe jetzt auch gesehen, wo zuvor meine Fehler waren.
    Wie es aussieht, lässt sich das Tutorial-Beispiel auch wunderbar übertragen.

    Danke

  8. The Following User Says Thank You to Powers For This Useful Post:

    dennis! (09.09.2013)

  9. #7
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Also eine Besonderheit ist jetzt noch offen: Wie lagere ich das ganze in ein Fieldset aus?

    Wenn ich ein Formular direkt aufrufe, dann klappt alles:
    PHP-Code:
    public function testformAction()
    {
            
    $entityManager $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
            
    $form = new \Application\Form\MyForm($entityManager);
            return new 
    ViewModel(array(
                
    'form' => $form
            
    ));

    PHP-Code:
    namespace Application\Form;

    use 
    Zend\Form\Form;
    use 
    DoctrineModule\Persistence\ObjectManagerAwareInterface;
    use 
    Doctrine\Common\Persistence\ObjectManager;

    class 
    MyForm extends Form implements ObjectManagerAwareInterface
    {
        protected 
    $objectManager;

        public function 
    __construct(ObjectManager $objectManager)
        {
            
    $this->setObjectManager($objectManager);

            
    parent::__construct('db-adapter-form');

            
    $this->add(array(
                
    'type'    => 'DoctrineModule\Form\Element\ObjectSelect',
                
    'name'    => 'name',
                
    'options' => array(
                    
    'label'          => 'Dynamic ObjectManager Select',
                    
    'object_manager' => $this->getObjectManager(),
                    
    'target_class'   => 'Application\Entity\Author',
                    
    'property'       => 'firstname',
                    
    'empty_option'   => '--- please choose ---'
                
    ),
            ));
        }

        public function 
    setObjectManager(ObjectManager $objectManager)
        {
            
    $this->objectManager $objectManager;

            return 
    $this;
        }

        public function 
    getObjectManager()
        {
            return 
    $this->objectManager;
        }

    Aber in ein Fieldset ausgelagert, scheitert es leider am ObjectManager, der nicht mehr "mit sich reden lässt":
    PHP-Code:
    namespace Application\Fieldset;
    use 
    Application\Entity\Book;
    use 
    Zend\Form\Element;
    use 
    Zend\Form\Fieldset;
    use 
    DoctrineModule\Persistence\ObjectManagerAwareInterface;
    use 
    Doctrine\Common\Persistence\ObjectManager;
    use 
    DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;


    class 
    BookFieldset extends Fieldset implements ObjectManagerAwareInterface
    {
        protected 
    $objectManager;

        public function 
    setObjectManager(ObjectManager $objectManager)
        {
            
    $this->objectManager $objectManager;
            return 
    $this;
        }

        public function 
    getObjectManager()
        {
            return 
    $this->objectManager;
        }

        public function 
    __construct(ObjectManager $objectManager)
        {
            
    $om $this->setObjectManager($objectManager);

            
    parent::__construct('book');
            
    $this->setHydrator(new \Zend\Stdlib\Hydrator\Reflection());
            
    $this->setObject(new \Application\Entity\Book());

            
    $this->add(array(
                
    'name' => 'title',
                
    'attributes' => array(
                    
    'type' => 'text',
                    
    'id' => 'title'
                
    ),
                
    'options' => array(
                    
    'id' => 'title',
                    
    'label' => 'Buchtitel:',
                )
            ));

            
    $this->add(array(
                
    'type'    => 'DoctrineModule\Form\Element\ObjectSelect',
                
    'name'    => 'name',
                
    'options' => array(
                    
    'label'          => 'Dynamic ObjectManager Select',
                    
    'object_manager' => $this->getObjectManager(),
                    
    'target_class'   => 'Application\Entity\Author',
                    
    'property'       => 'firstname',
                    
    'empty_option'   => '--- please choose ---'
                
    ),
            ));
        }

    Da erscheint dann folgender Fehler: "Catchable fatal error: Argument 1 passed to Application\Fieldset\BookFieldset::__construct() must implement interface Doctrine\Common\Persistence\ObjectManager, none given, called in C:\xampp\htdocs\xxxxxxxx\vendor\zendframework\zend framework\library\Zend\ServiceManager\AbstractPlug inManager.php on line 170 and defined in C:\xampp\htdocs\xxxxxxxx\module\Application\src\Ap plication\Fieldset\BookFieldset.php on line 28"

    Line 28 entspricht der Zeile: "public function __construct(ObjectManager $objectManager)"
    Geändert von Powers (14.08.2013 um 20:41 Uhr)

  10. #8
    Erfahrener Benutzer
    Registriert seit
    18.05.2012
    Beiträge
    156
    Thanks
    5
    Thanked 29 Times in 22 Posts

    Standard

    Mir fehlt jetzt irgendwie die Stelle, an welcher du BookFieldset aufrufst. Aber das Problem ist klar: Es müsste ein ObjectManager als Parameter übergeben werden, jedoch macht er das nicht. Vermutlich hast du jetzt ganz normal dein Fieldset bei "type" eingetragen, oder? Anstelle des Arrays könntest du dann einfach eine Variable, welcher du new BookFieldset($om) zugeordnet hast, hinzufügen. Das wäre zumindest die erste Idee, die ich hätte. Ob das jetzt die gängige/beste Vorgehensweise ist, weiß ich nicht.


    Was mir auch noch auffällt:

    PHP-Code:
    $om $this->setObjectManager($objectManager); 
    mach dort bitte das $om davor, ich habe sonst Angst, dass du die Variable zukünftig als objectManager nutzen möchtest Der Rückgabewert vom setter ist nämlich nicht der objectManager, sondern $this - also das BookFieldset.

  11. #9
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Ja stimmt, dass $om war auch nur eine Sache / Versuch von einer Quelle, die ich mal ausprobiert habe :-)

    Also ich habe halt schon ne kleine Verkettung.
    Im ersten Versuch habe ich den ObjectSelect direkt im Formular selbst aufgerufen. Anstatt des direkten Aufrufs wird dort nun ein Fieldset aufgerufen:
    PHP-Code:
    //Formular
    $this->add(array(
           
    'type' => 'Application\Fieldset\ArticleFieldset',
            
    'options' => array(
                
    'use_as_base_fieldset' => true
            
    )
    )); 
    In diesem Fieldset wird wiederrum das nächste Fieldset aufgerufen:

    PHP-Code:
    //ArticleFieldset
    $this->add(array(
          
    'type' => 'Application\Fieldset\BookFieldset'
    )); 
    Und dort im BookFieldset befindet sich dann das oben aufgeführte Fieldset. Ich habe mir auch schon gedacht, dass ich den Objektmanager da durchschleusen muss.
    Soll das dann etwa so aussehen?

    PHP-Code:
    //Formular
    $this->add(array(
            
    'type' => 'Article\Fieldset\ArticleFieldset',
            
    'options' => array(
                
    'use_as_base_fieldset' => true,
                    
    'objekt_manager' => $this->getObjectManager(),
            )
    )); 
    Mache mich morgen wieder dran
    Geändert von Powers (14.08.2013 um 23:19 Uhr)

  12. #10
    Erfahrener Benutzer
    Registriert seit
    18.05.2012
    Beiträge
    156
    Thanks
    5
    Thanked 29 Times in 22 Posts

    Standard

    Nein, das wird vermutlich nicht klappen, weil ZF2 die Eigenschaft wohl nicht kennen wird. Ich würde mal folgendes ausprobieren:

    PHP-Code:
    $bookFieldset = new Article\Fieldset\BookFieldset($this->getObjectManager());
    $bookFieldset->setOptions(array('use_as_base_fieldet' => true));
    $this->add($bookFieldset); 
    Ist jetzt nur hier frei eingetippt und ungetestet. Gleiches Spiel dann vermutlich auch mit dem ArticleFieldset.

  13. #11
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Ja super, mit dieser Schreibweise klappt das hervorragend. Ich kann den Objektmanager vom Grundformular bis ins letzte Fieldset durchreichen.
    Ich fand die "$this->add" Array-Schreibweise ziemlich praktisch. Aber ich mag es Einheitlich und steige dann wohl sogar auf die nun vorgeschlagene Schreibweise um.

    Vielen Dank jedenfalls nochmal

    Einzige Sache für Nachahmer, die sich über einen Fehler beim implementieren wundern - noch ein Backslash kommt an den Anfang des Fieldsets-Aufrufs:
    PHP-Code:
    $bookFieldset = new \Article\Fieldset\BookFieldset($this->getObjectManager());
    $bookFieldset->setOptions(array('use_as_base_fieldet' => true));
    $this->add($bookFieldset); 

  14. #12
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Puh, ich muss zugeben das ich beim speichern der Objekte wiederrum grandios gescheitert bin heute :-/ Ich habe da eine riesige Verständnislücke, wie mir scheint.

    Da die Book-Entity der Owner der Author-Entity ist, habe ich nun auf ein extra-Fieldset verzichtet und den "ObjectSelect" ebenefalls in das Book-Fieldset gepackt (und nicht in ein weiteres, seperates Author-Fieldset).

    Dort bekomme ich nun den Fehler: "Found entity of type on association Article\Entity\Bkbook#authors, but expecting Article\Entity\Bkauthor"

    Ich vermute jedoch, dass der Fehler ggf nichtmal in die Nähe von dem kommt, wo ich eigentlich hin möchte (und zwar, dass zu dem neu angelegten Buch die Authoren schlicht in der Referenztabelle als Relation angelegt werden).

    PHP-Code:
    <?php
    namespace Article\Fieldset;

    use 
    Article\Entity\Bkbook;

    use 
    Zend\Form\Element;
    use 
    Zend\Form\Fieldset;
    use 
    DoctrineModule\Persistence\ObjectManagerAwareInterface;
    use 
    Doctrine\Common\Persistence\ObjectManager;
    use 
    DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;


    class 
    BookFieldset extends Fieldset implements ObjectManagerAwareInterface
    {
        protected 
    $objectManager;

        public function 
    setObjectManager(ObjectManager $objectManager)
        {
            
    $this->objectManager $objectManager;
            return 
    $this;
        }

        public function 
    getObjectManager()
        {
            return 
    $this->objectManager;
        }

        public function 
    __construct(ObjectManager $objectManager)
        {
            
    $this->setObjectManager($objectManager);

            
    parent::__construct('book');
            
    $this->setHydrator(new \Zend\Stdlib\Hydrator\Reflection());
            
    $this->setObject(new \Article\Entity\Bkbook());
        
    //    $this->setHydrator(new DoctrineHydrator($objectManager, '\Article\Entity\Bkbook'));

            
    $this->add(array(
                
    'name' => 'title',
                
    'attributes' => array(
                    
    'type' => 'text',
                    
    'id' => 'title'
                
    ),
                
    'options' => array(
                    
    'id' => 'title',
                    
    'label' => 'Buchtitel:',
                )
            ));

            
    $this->add(array(
                
    'type'    => 'DoctrineModule\Form\Element\ObjectSelect',
                
    'name'    => 'authors',
                
    'attributes' => array(
                    
    'multiple' => 'multiple',
                    
    'required' => true
                
    ),
                
    'options' => array(
                    
    'label'          => 'Buchautor/en',
                    
    'object_manager' => $this->getObjectManager(),
                    
    'target_class'   => 'Article\Entity\Bkauthor',
                    
    'value'             => 'id',
                    
    'property'       => 'lastname',
                    
    'empty_option'   => '--- please choose ---',

                ),
            ));
    /*
            $bookauthorSelect = new \Article\Fieldset\BookauthorSelect($this->getObjectManager());
            $bookauthorSelect->setOptions(array('use_as_base_fieldset' => true));
            $this->add($bookauthorSelect);
    */
        
    }


    }
    Verbunden sind die beiden Entitäten so (ManyToMany bidirektional):
    PHP-Code:
    // Book Entität
    /**
        * @ORM\ManyToMany(targetEntity="Bkauthor", inversedBy="authors")
        * @ORM\JoinTable(name="bk_authors_books",
        *         joinColumns={@ORM\JoinColumn(name="book_id", referencedColumnName="id")},
        *         inverseJoinColumns={@ORM\JoinColumn(name="author_id", referencedColumnName="id")}
        * )
        */
        
    protected $authors
    PHP-Code:
    // Author Entität
    /**
        * @ORM\ManyToMany(targetEntity="Bkbook", mappedBy="book")
        * @ORM\JoinTable(name="bk_authors_books",
        *         joinColumns={@ORM\JoinColumn(name="author_id", referencedColumnName="id")},
        *         inverseJoinColumns={@ORM\JoinColumn(name="book_id", referencedColumnName="id")}
        * )
        */
        
    protected $book
    Also es scheint klar, dass mit dem Reflection-Hydrator in der Richtung nicht viel laufen kann. Schließlich bin ich bei dem ObjectSelect ja davon abhängig, dass Objekte für das Formular "lesbar" gemacht werden und anschließend als Objekte wieder rausgehen, richtig? Av3nger hatte ja anfangs direkt vom DoctrineObject Hydrator geschrieben, der da standardmäßig benutzt wird.

    Das Book-Fieldset bringe ich mit dem DoctrineObject-Hydrator aber wohl durcheinander. Und auf ein eigenes Fieldset habe ich nun erstmal verzichtet, weil es wie gesagt nicht meiner Doctrine-Struktur entspricht und es ohnehin dazu geführt hat, dass Doctrine schlicht neue Autoren-Objekte erstellt hat beim versenden.

    Ja sorry für diese riesige Verständnislücke, ich bin da echt dran gegangen, konnte die Sachen so aber erstmal nicht zusammenführen und meine beiden ZendFramework Bücher (Eggert / Romer), als auch das Doctrine Buch (Romer) haben dazu leider auch nichts auf Lager. Der einzige Ansatz den ich grad sehe, wäre ein eigener Hydrator, wie in Eggert ZF2 in Listing 12.23 beschrieben. Aber ich glaube das wäre garnicht das, was ein muss.

    Ja blöd das dieser Schritt für mich noch so zäh ist. Aber es ist der letzte bedeutende Schritt in meinem Projekt, deswegen bin ich da wirklich dabei und versuche es.

  15. #13
    Erfahrener Benutzer
    Registriert seit
    18.05.2012
    Beiträge
    156
    Thanks
    5
    Thanked 29 Times in 22 Posts

    Standard

    Meine Vermutung wäre jetzt erst mal eine andere, kann jedoch sein, dass ich damit jetzt aber völlig daneben liege. Ich habe nämlich die Annotationen im Verdacht. Bei inversedBy müsste eher book anstelle von authors und bei mappedBy dann authors statt book drin stehen, also jeweils die Variable der anderen Klasse.

    Das ist erst mal nur das erste, was mir auffiel. Hinsichtlich ZF2 mit Doctrine2 bin ich selbst noch irgendwo am Anfang des Lernprozesses. Irgendwie fehlt es da an brauchbarer Dokumentation, da im ZF2-Manual darauf natürlich nicht eingegangen wird, weil es kein Bestandteil vom Framework ist, und im Doctrine2-Manual wiederum nicht, weil's dort eher Framework-unabhänig beschrieben ist. Das einzige, was vorzufinden ist, ist ja eher der docs-Ordner vom DoctrineModule - und halt einige Blog-Einträge. Vielleicht sollte ich selbst mal einige Artikel mit den bisherigen Erkenntnissen schreiben.

  16. #14
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Ja, dass ist wirklich so, dass weder die Zend-Literatur, noch die Doctrine-Literatur diesen Part abdeckt. Da wird die Zuständigkeit quasi ins Nirgendwo abgeschoben (was wiederrum verständlich ist, wenn auf jeder Seite jeweils die notwendigsten Dinge abgehandelt werden sollen).

    Nun denn, das heißt wohl einen Kaffee machen und alles nochmal vom Grund aus aufrollen. Da wird irgendwo ein ganz grober Fehler gemacht.

    LG
    Geändert von Powers (16.08.2013 um 14:11 Uhr)

  17. #15
    Benutzer Avatar von hoagster
    Registriert seit
    08.03.2008
    Ort
    Hamburg
    Beiträge
    40
    Thanks
    1
    Thanked 5 Times in 2 Posts

    Standard

    edit: Habe av3ngers Antwort überlesen, sorry

    Hi Powers,

    Zitat Zitat von Powers Beitrag anzeigen
    Dem Verdacht, dass schlicht beim Mapping was nicht stimmt, habe ich auch ständig vor Augen.
    das stimmt schon mal
    inversedBy und mappedBy sind falsch rum gesetzt

    PHP-Code:
    // Book Entität
    /**
     * @ORM\ManyToMany(targetEntity="Bkauthor", inversedBy="books")
     * @ORM\JoinTable(name="bk_authors_books")
     */
    protected $authors;

    // Author Entität
    /**
     * @ORM\ManyToMany(targetEntity="Bkbook", mappedBy="authors")
     * @ORM\JoinTable(name="bk_authors_books")
     */
    protected $books
    Siehe dazu auch 5. Association Mapping - Doctrine 2 ORM 2.0.0 documentation

    Ich habe in den Annotations Teile entfernt, der Doctrine 2 standard ist.
    Das es eine many to many (bidirektionale) Assoziation ist, sollte der Klarheit halber "book" "books" heißen.
    Geändert von hoagster (16.08.2013 um 14:18 Uhr)

  18. #16
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Heureka, es klappt
    Kaffee und viel Geduld sind doch immer eine gute Lösung

    @Hoagster
    Ja, mit dem plural bei "books" hast Du völlig recht. Die Singularform ist auch hier mal wieder durch ausprobieren reingerutscht und ist natürlich unsinn. Und das Mapping werd ich insgesamt nochmal Prüfen. Beim auslesen mag Doctrine einem sowas verzeihen, aber nicht bei einlesen

    Ich versuche mal meine Lösung für Nachahmer darzustellen. Der Erfolg kam mit der Umsetzung von diesem Beispiel:
    Zend Framework - ZF2 Using the same Fieldset multiple names with different names

    Und zwar rufe ich mein Fieldset nun folgend auf:
    PHP-Code:
    // Form oder Fieldset, dass ein weiteres Fieldset aufruft
    $bookauthorSelect = new BookauthorSelect($objectManager);
       
    $this->add(array(
          
    'type' => 'Zend\Form\Element\Collection',
          
    'name' => 'authors',
          
    'options' => array(
     
    //        'label' => 'Leagues',
               
    'should_create_template' => true,
               
    'allow_add' => true,
               
    'target_element' => $bookauthorSelect,
        ),
    )); 
    Und das Fieldset bleibt entsprechend so. Nur eines war ganz wichtig: bei 'name' wird nun 'id' zugewiesen (!).
    PHP-Code:
    //Fieldset welches den ObjectSelect beinhaltet
    public function __construct(ObjectManager $objectManager)
    {
        
    $this->setObjectManager($objectManager);

        
    parent::__construct('authors');
        
    $this->setHydrator(new DoctrineHydrator($objectManager'Article\Entity\Bkauthor'));
        
    $this->setObject(new \Article\Entity\Bkauthor());

        
    $this->add(array(
            
    'type'    => 'DoctrineModule\Form\Element\ObjectSelect',
            
    'name'    => 'id',
      
    //    'attributes' => array(
      //        'multiple' => 'multiple',
      //    ),
            
    'options' => array(
                
    'label'          => 'Buchautor/en',
                
    'object_manager' => $this->getObjectManager(),
                
    'target_class'   => 'Article\Entity\Bkauthor',
                
    'value'            => 'id',
                
    'property'       => 'lastname',
                
    'empty_option'   => '--- bitte wählen ---',
            ),
        ));

    Und auch wenn ich damit jetzt schonmal leben kann, ist da dennoch ein verbleibender Stolperstein, wenn man mehrere Autoren aufeinmal zu einem Buch abspeichern möchte (also das multiple => multiple wieder mit reinnehme). Der Fehler lautet dann:
    "Notice: Array to string conversion in C:\xxx\xxx\xxx\vendor\doctrine\orm\lib\Doctrine\OR M\UnitOfWork.php on line 2791"

    Und dieser Fehler wird klar, wenn man sich das übergebene Array anschaut, wo anstelle der Autor-ID nun ein neues Array erscheint (welches den Fehler erzeugt, da ein String erwartet wird):
    PHP-Code:
    //var_dump auf "book->authors"
    array   
       
    =>      
        
    object(Article\Entity\Bkauthor)[488]       
        protected 
    'id' =>          
            array           
               
    => string '1' (length=1)           
               
    => string '2' (length=1)       
          protected 
    'firstname' => string 'Brian' (length=5)       
          protected 
    'lastname' => string 'Lumley' (length=6)       
          protected 
    'date_of_birth' => string '0000-00-00' (length=10)       
          protected 
    'date_of_death' => string '0000-00-00' (length=10)       
          protected 
    'gender' => string '' (length=0)       
          protected 
    'information_text' => string '' (length=0)       
    ...... 
    Zum Vergleich die wohlgeordnete Ausgabe, wenn nur ein Autor mit hinein gegeben wird (da klappts dann auch mit dem speichern, als einheitliches Objekt):
    PHP-Code:
    //var_dump auf "book->authors"
    array   
        
    =>      
        
    object(Article\Entity\Bkauthor)[488]       
        protected 
    'id' => string '1' (length=1)       
        protected 
    'firstname' => string 'Brian' (length=5)       
        protected 
    'lastname' => string 'Lumley' (length=6)       
        protected 
    'date_of_birth' => string '0000-00-00' (length=10)       
        protected 
    'date_of_death' => string '0000-00-00' (length=10)       
        protected 
    'gender' => string '' (length=0)       
        protected 
    'information_text' => string '' (length=0)
    ..... 
    Hat da vielleicht noch jemand einen Vorschlag? Ansonsten bin ich schonmal froh für den Moment
    Geändert von Powers (16.08.2013 um 17:02 Uhr) Grund: Code lesbarer gemacht

  19. #17
    Benutzer Avatar von hoagster
    Registriert seit
    08.03.2008
    Ort
    Hamburg
    Beiträge
    40
    Thanks
    1
    Thanked 5 Times in 2 Posts

    Standard

    Meiner Meinung nach müsste im ObjectSelect für "name" "authors" statt "id" gesetzt werden?

  20. #18
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Das klingt logisch.

    Aber wenn ich das mache, dann werden die ausgewählten Objekte vom Formular leider nicht weitergereicht. Stattdessen wird beim abschicken des Formulares einfach ein leeres Objekt mit den Properties der authors-Entity erstellt.

    Umstellen des Formulares:
    PHP-Code:
    public function __construct(ObjectManager $objectManager)
        {
       
    $this->setObjectManager($objectManager);

            
    parent::__construct('authors');
            
    $this->setHydrator(new DoctrineHydrator($objectManager'Article\Entity\Bkauthor'));
            
    $this->setObject(new \Article\Entity\Bkauthor());

            
    $this->add(array(
                   
    'type'    => 'DoctrineModule\Form\Element\ObjectSelect',
                   
    'required' => FALSE,
                   
    'name'    => 'authors',
                   
    'attributes' => array(
                          
    'multiple' => 'multiple',
                   ),
                   
    'options' => array(
                          
    'label'          => 'Buchautor/en',
                          
    'object_manager' => $this->getObjectManager(),
                          
    'target_class'   => 'Article\Entity\Bkauthor',
                          
    'value'             => 'id',
                          
    'property'       => 'lastname',
                          
    'empty_option'   => '--- bitte wählen ---',
                  ),
            ));
        } 
    führt zu:

    PHP-Code:
    array  
       
    =>     
          
    object(Article\Entity\Bkauthor)[426]      
             protected 
    'id' => null      
             
    protected 'firstname' => null      
             
    protected 'lastname' => null       
             
    protected 'gender' => null 
    Wenn bei 'name' die 'id' eingetragen wird, könnten einzelne Objekte vom Formular übergeben werden.
    Aber bei einer multiplen Auswahl wird nach wie vor nur ein Objekt der Klasse Author erstellt, nur dass der ID-Eintrag des Author-Objektes dann alle ausgewählten ID's als array beinhaltet, was zu einer "Array to string conversion"-Fehlermeldung führt (und ja eeh so keinen Sinn macht).
    Was muss man umstellen, damit wirklich mehrere Authoren-Objekte weitergegeben werden, und nicht nur eines?
    Geändert von Powers (07.09.2013 um 18:55 Uhr) Grund: Ergänzung

  21. #19
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Mal eine Verständnisfrage zum speichern von mehreren Objekten einer Entität:

    Wenn ein Autor zu einem Buch gespeichert werden soll, wird dafür einfach die Autor-Entität herangezogen und die Relation Buch - Autor wird gespeichert.
    Aber wenn ich mehrere Autoren zu einem Buch speichern möchte (multiple bei ObjektSelect), dann führt das zu fehlern.

    Ändert sich diese Vorgehensweise, wenn mehrere Autoren zu einem Buch gespeichert werden sollen?
    Muss anstelle der Autoren Entität ggf die Buch-Entität aufgerufen werden, die ja die Property "authors" enthält?
    Ähnlich wie in dieser Quelle hier: Doctrine is an object relational mapper (ORM) for PHP that sits on top of a powerful database abstraction layer (DBAL). Doctrine User mailing list. For questions regarding installation and usage of doctrine.

    Dort werden dann (äquivalent gesagt) in der Buch-Entität die property in Mehrzahl von "autoren" aufgerufen. Mithilfe von weitere get, add und remove-Funktionen ein Austausch gewährleistet.

    Leider auch bei dieser Umsetzung die Fehlermeldung: "Fatal error: Call to a member function toArray() on a non-object in C:\xxx\xxx\xxx\vendor\doctrine\doctrine-module\src\DoctrineModule\Stdlib\Hydrator\Strategy \AllowRemoveByValue.php on line 57"

    Ist das der richtige Ansatz? Aber wenn ja, warum?

  22. #20
    Erfahrener Benutzer
    Registriert seit
    18.08.2010
    Beiträge
    110
    Thanks
    7
    Thanked 1 Time in 1 Post

    Standard

    Eine Sache, die ich schon länger nachreichen wollte für Leute, die auf ähnliche Probleme stoßen, wenn sie eine ManyToMany-Relation mit dem Hydrator verarbeiten wollen:
    Ich bin zu der Erkenntnis gekommen, dass dies nicht (einfach so) möglich ist. Aus diesem Grund bin ich bei der Verarbeitung in Doctrine-Klassen auch immer wieder auf Fehler gestoßen, wenn ein Array, anstelle eines einzigen Strings übergeben wurde.

    Gehen wir von diesem Beitrag aus, der die Arbeitsweise des Hydrators darstellt:
    https://github.com/josielrocha/ZF2--...cs/hydrator.md

    Es werden "OneToOne", "OneToMany" und "ManyToOne" erklärt. Aber -kein- "ManyToMany".
    Warum das so ist, wird klar, wenn man den unmittelbaren Verwendungszweck des Hydrators überdenkt:

    In meinem Fall möchte ich zu einem Buch mehrere Autoren speichern. Da ein Autor auch mehrere Bücher haben kann, habe ich mich bei der Modellierung für eine MayToMany-Relation entschieden, wobei Bücher und Autoren durch eine NM-Tabelle verbunden werden.

    Wollen wir das jedoch auf den vorliegenden Fall anwenden, bekommen wir ein Problem. Denn beim erstellen eines Buches, können wir zwar mehrere Autoren auswählen (das ist erlaubt). Aber reduziert auf diese Formular-Verarbeitung haben wir eine OneToMany-Relation. Ein Buch -> mehrere Autoren.
    Da wird klar, warum der Hydrator keine ManyToMany-Verarbeitung anbietet. Reduziert auf den Formularzweck macht es schlicht keinen Sinn.

    Bei der Verarbeitung stoßen die aufbereiteten Informationen aus dem Hydrator (in Form von OneToMany) intern dann auf meine zuvor gebaute "ManyToMany"-Architektur. Und an dieser Stelle knallt es.

    Das zeigt sich auch dadurch, dass, wenn man hingehend alles korrekt konfiguriert, der Fehler kommt, dass die Autoren keine "buch_id" besitzen. An der Stelle wird es dann wohl interessant, weil man nun eine OneToMany-Relation in Doctrine mit einer NM-Tabelle verbinden müsste, damit keine sinnlosen Redundanzen auftreten (Wir wollen ja nicht 10x einen Autor in der Autoren-Tabelle anlegen, nur weil er 10 Bücher geschrieben hat).

    Über Antworten zur Sache und Lösungen würd ich mich freuen. Es liegt zwar kein akutes Problem vor, ist aber interessant
    Geändert von Powers (08.10.2013 um 13:27 Uhr)

Seite 1 von 2 1 2 LetzteLetzte

Ähnliche Themen

  1. Form mit Doctrine 2 Entity verbinden
    Von roman1983 im Forum ZF2 Formulare
    Antworten: 2
    Letzter Beitrag: 12.03.2013, 17:08
  2. Doctrine 2 Entity testen
    Von laubegaster im Forum ZF2 DB
    Antworten: 4
    Letzter Beitrag: 05.03.2013, 15:06
  3. Antworten: 1
    Letzter Beitrag: 04.03.2013, 19:38
  4. Doctrine 2 Entity erweitern um Werte die nicht in der DB stehen
    Von claudia.sagner im Forum 3rd Party Tools
    Antworten: 2
    Letzter Beitrag: 23.01.2013, 11:38
  5. Doctrine 2 Entity erweitern um Werte die nicht in der DB stehen
    Von claudia.sagner im Forum ZF2 Einsteigerfragen
    Antworten: 0
    Letzter Beitrag: 22.01.2013, 17:10

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •