Mysql Query -> Activerecord

Hallo,

wie kann ich das Ergebnis, das mir untenstehende MySQL Abfrage bringt, erreichen mit ActiveRecord?

Die Tabellen:


Noten         Id, Werk, Verlag_Id, Sammelheft_Id

Sammelhefte   Id, Titel, Verlag_Id

Verlage       Id, Name


SELECT n.Id, Werk, s.Titel, v1.Name, v2.Name 

FROM Noten AS n

LEFT JOIN Sammelhefte AS s ON n.Sammelheft_Id = s.Id

LEFT JOIN Verlage AS v1 ON n.Verlag_Id = v1.Id

LEFT JOIN Verlage AS v2 ON s.Verlag_Id = v2.Id

Die Relations im Model "Noten" habe ich so definiert:


public function relations() {

        return array(

            'Verlag'=>array(self::BELONGS_TO, 'Verlage', 'Verlag_Id'),

            'Sammelheft'=>array(self::BELONGS_TO, 'Sammelhefte', 'Sammelheft_Id'),

        );

}

Die search Methode beginnt so:


       public function search() {

            $criteria=new CDbCriteria;          

            $criteria->with = array('Verlag','Sammelheft');

Muss ich bei den Relationen etwas ändern oder bei den Kriterien oder beides … ?

Danke für Nachsicht und Hilfe.

Ferdinand

Sieht eigentlich alles solide aus. Haben deine Sammelhefte auch Relationen auf Verlage definiert? Sonst könnte es schwierig werden, v2.Name aus deiner alten Abfrage nachzubauen.

Bei den Kriterien würde ich aber überlegen, ob das with wirklich nötig ist. Mit CDbCriteria.compare() kannst du direkt verwandte Felder angeben. Also z.B. $criteria->compare(‘Verlag.name’,$verlagsName).

Danke für deinen Versuch, mir zu helfen.

Im Model "Sammelhefte" habe ich die Relation definiert:


public function relations()

{

        return array(

            'Verlag'=>array(self::BELONGS_TO, 'Verlage', 'Verlag_Id'),

        );

}

Ich hätte gedacht, das "with" bewirkt, dass alles gemeinsam in eine Tabelle geladen wird (eager loading), also wie eine Abfrage mit Joins ohne Verwendung von CActiveRecord …

Aber lassen wir das einmal beiseite.

Leider stehe ich so abseits, dass ich nicht kapiere, wie ich die zusätzliche Relation der Tabelle "Sammelhefte" zu der Tabelle "Verlage" da hineinkriege. Wie kann ich im Model "Noten" diese zweite Relation zur Tabelle "Verlage" definieren?

Im Model "Noten" ist ja nur die Relation "Noten" zu "Verlage" definiert.

Oder anders gefragt: Kann ich die Relation, die im Model "Sammelhefte" difiniert ist, im Model Noten verwenden und, wenn ja, wie baue ich die dann ein?

Tut mir leid, mir fehlt einfach der Durchblick …

Also, ich habe es jetzt geschafft durch Hinzufügen eines Alias in der with Eigenschaft von [b]CDbCriteria.

[/b]


public function search() {

    $criteria=new CDbCriteria;

    $criteria->with = array('Verlag',

                            'Sammelheft',

                            'Sammelheft.Verlag'=>array('alias'=>'Verlag_Sammelheft'));

    

    $criteria->compare('Verlag.Name',$this->Name_Verlag,true);

    $criteria->compare('Verlag_Sammelheft.Name',$this->Name_Verlag,true,'OR');

    ...



Ich erhalte jetzt also zwei Spalten mit dem Namen des Verlags (über den Fremdschlüssel Verlag_Id - entweder aus der Tabelle Noten oder aus der Tabelle [b]Sammelhefte.

[/b]

Als Draufgabe lefert mir folgende Funktion noch den Namen des Verlags, sodass ich diesen dann in einer einzigen Spalte anzeigen kann:


public function getValue($fieldName) { 

    if ( $this->Sammelheft_Id > 0 ) $value = $this->Sammelheft->$fieldName;

    else $value = $this->$fieldName;

    return $value;

}

In CGridView wird diese Spalte dann so angezeigt:


'columns'=>array(

	array('name'=>'Name_Verlag', 'value'=>'$data->getValue("Name")'),

Man kann in dieser Spalte auch suchen. Sortieren geht aber nicht.

Ich bin trotzdem zufrieden :rolleyes:

Puh … Ich bin etwas skeptisch, was getValue() angeht. Schließlich verliert man doch ziemlich übel die Kontrolle darüber, welches Feld man jetzt genau anfordert.

In der GridView bin ich übrigens der Ansicht, dass das selbe Ergebnis auch mit ‘name’=>‘Sammelheft.Name’ zu erreichen sein sollte.

Ich habe in der Tabelle Noten und in der Tabelle Sammelhefte mehrere gleiche Feldnamen. Es steht in diesen gleichlautenden Feldern entweder in der einen Tabelle ein Wert oder in der anderen. Die Methode getValue() liefert mir von jeder dieser doppelt vorhandenen Spalten nur einen Wert. Zur Verdeutlichung ein größerer Ausschnitt aus der GridView:


'columns'=>array(

	array('name'=>'Werk', 'htmlOptions'=>array('width'=>'100px')),

	array('name'=>'Titel_Sammelheft', 'value'=>'$data->Sammelheft->Titel'),

	array('name'=>'Name_Verlag', 'value'=>'$data->getValue("Name")'),

	array('name'=>'Nr_Verlag', 'value'=>'$data->getValue("Verlag_Nr")'),

	array('name'=>'Reihe_Verlag', 'value'=>'$data->getValue("Reihe")'),

	array('name'=>'Anmerkung_Werk', 'value'=>'$data->getValue("Anmerkung")'),

...

Ich sehe, da hast du anscheinend Recht. Aber die Bezeichnung ist für mich irreführend, da ja der Name des Verlags, der in dieser Spalte angezeigt wird, auch aus der Tabelle Noten kommen kann …

Ein wenig überkompliziert, ich gebe es zu. :rolleyes: