MANY MANY Relation speichern

Hallo,

ich habe eine many to many Relation zwischen User und User, die wie folgt aussieht.




return array(

   'friends' => array(self::MANY_MANY, 'User', 'tbl_user_friend(user_id, user_friend_id)'),                     		

);



Habe in der Tabelle tbl_user_friend auch ein paar Einträge gemacht und die Relations werden soweit auch im jeweiligen User Objekt korrekt erfasst.

Jetzt habe ich nur 2 Probleme.

  1. Wie kann ich einem User jetzt Freunde zuweisen und wie sorge ich dafür, dass diese auch beim speichern, in die entsprechende Tabelle eingetragen werden.

  2. Wie kann ich in einem View des Users, seine Freunde in einem Gridview, oder anderen geeigneten Widgets ausgeben ? Das Gridview erwartet einen Dataprovider oder ? Wie komme ich an diesen dran ?

Ich habe im Forum gestöbert und auch im Guide, jedoch haben die Artikel die ich zu Relations gefunden habe mir nicht wirklich weiter geholfen.

Danke schonmal für die Hilfe.

Hi,

ich versuchs mal

Automatisch geht das Speichern in die tbl_user_friend meines Wissens nach nicht aber es gibt die CAdvancedArBehavior Extension die dir da weiterhelfen könnte.

[font="arial, verdana, tahoma, sans-serif"][size="2"]

Ein Dataprovider bereitet die Daten in so einer Form auf das diese in einem Gridview oder sonstigem Anzeige-Widget einfach ausgegeben werden können. Dem CActiveDataProvider übergibst du beim Aufruf die Model Klasse (User in deinem Fall) als ersten und das Konfigurationsarray als zweiten Parameter.[/size][/font]

[font="arial, verdana, tahoma, sans-serif"][size="2"]Schau dir dazu auch nochmal den Guide zu relationalen Abfragen an und speziell den Teil wie man Tabellen z.B. mit with "joinen" kann.[/size][/font]

Ich habe es mal mit CAdvancedArBehavior probiert. Erhalte nun eine Exception:

Eigenschaft "User.user_friend_id ist nicht definiert.

Die Exception ist soweit auch richtig, denn der Primary-Key in User heißt ‘id’.

Also dachte ich mir, versuche ich es wie folgt:




      'friends' => array(self::MANY_MANY, 

                         'User', 

                         'tbl_user_friend(user_id, user_friend_id)', 

                         'having'=>array('user_id'=>'id', 'user_friend_id'=>'id')

                        )

                );



Die Exception ist immernoch die selbe.

OK habs jetzt endlich. Funktioniert soweit ganz gut mit der CAdvancedArBehavior Extension.

Also meine Relation im Model sieht nun wie folgt aus:




return array(

      'friends' => array(self::MANY_MANY, 

                         'User', 

                         'tbl_user_friend(user_id, user_friend_id)', 

                        )

                );



In der jeweiligen Methode, die beim speichern des Models auch die many to many Tabelle updaten soll, füge ich vor dem Aufruf von save() folgendes ein:




$model->attachBehavior('CAdvancedArBehavior', array('class' => 'application.extensions.CAdvancedArBehavior.CAdvancedArBehavior'));



Das Anhängen kann optional auch in der behaviors Methode des Models geschehen

, führt aber dazu, dass bei jedem Speichervorgang des Models, alle Datensätze in der Relationen-Tabelle gelöscht und neu erstellt werden. Ich denke mit attachBehavior() ist das ganze etwas effizienter.

In der Extension musste ich eine kleine Änderung vornehmen …




//$foreignobject = $foreignobject-{$foreignobject->$relation['m2mForeignField']};	

// ersetzen mit			

$foreignobject = $foreignobject->getPrimaryKey();  



… da sonst im Model nach der Eigenschaft ‘user_friend_id’ gesucht wurde. Das ist aber nur der Name der Spalte in der Relationen-Tabelle. Nach der Änderung wird einfach der Primary-Key genommen.

So können jetzt die Relationen, in meinem Fall ‘friends’, erstellt werden:




      $friends = array();

      // PKs der vorhandenen Freunde in $friends[] ablegen.

      foreach($model->friends as $friend) {           

        $friends[] = $friend->id;    

      }

      // neuen Freund hinzufügen

      $friends[] = User::model()->findByPk(64); 

      $model->friends = $friends;


      // Beim Aufruf von $model->save() wird die Relationen Tabelle nun aktualisiert



Das ganze ist jetzt nur noch etwas ineffizient, da beim update der Relationen-Tabelle alle Datensätze gelöscht und neu eingefügt werden. Sprich, bei 200 Freunden des Users führt ein update zu 200 Querys, um die Freunde-Tabelle zu aktualisieren.

Wenn ich das etwas effizienter hinkriege poste ich es hier. Wenn jemand Tipps hat bezüglich der Effizienz, sind diese hier gerne willkommen.

Danke an kokomo für die Tipps und danke an thyseus für die Extension.