2014-12-29 6 views
15

ich drei Datenbanktabelle haben:Active wo und Ordnung auf über Tisch

Produkt (id, name)

product_has_adv (Produkt, Vorteil, sortieren, wichtig)

Vorteil (id, Text

)

In Product I definiert sind dies:

public function getAdvantages() 
    { 
     return $this->hasMany(AdvantageModel::className(), ['id' => 'advantage']) 
      ->viaTable('product_has_advantage', ['product' => 'id']); 
    } 

ich erhalte die advanta ges ohne Probleme.

Aber jetzt muss ich hinzufügen, wo product_has_advantage.important = 1 clausel und auch die Vorteile durch die Sortierung-columen in der product_has_advantage-Tabelle sortieren.

Wie und wo muss ich es realisieren?

+0

siehe meine Antwort: http://stackoverflow.com/a/41539132/800639 –

Antwort

31

Die Verwendung von via und viaTable Methoden mit Beziehungen führt zu zwei separaten Abfragen.

Sie können in dritter Parameter wie folgt aufrufbar angeben:

public function getAdvantages() 
{ 
    return $this->hasMany(AdvantageModel::className(), ['id' => 'advantage']) 
     ->viaTable('product_has_advantage', ['product' => 'id'], function ($query) { 
      /* @var $query \yii\db\ActiveQuery */ 

      $query->andWhere(['important' => 1]) 
       ->orderBy(['sort' => SORT_DESC]); 
     }); 
} 

Der Filter von important wird angewendet werden, aber die Art nicht, da in der ersten Abfrage geschieht. Als Ergebnis wird die Reihenfolge der IDs in der IN Anweisung geändert.

Abhängig von Ihrer Datenbanklogik ist es vielleicht besser, important und sort Spalten zu advantage Tabelle zu verschieben.

Dann fügen Sie einfach Zustand und sortieren, um die bestehende Methode Kette:

public function getAdvantages() 
{ 
    return $this->hasMany(AdvantageModel::className(), ['id' => 'advantage']) 
     ->viaTable('product_has_advantage', ['product' => 'id']) 
     ->andWhere(['important' => 1]) 
     ->orderBy(['sort' => SORT_DESC]); 
} 
+0

Diese in den folgenden Fehlern führt: SQLSTATE [42S22]: Column nicht gefunden: 1054 Unknown column 'product_has_advantage.important' in ‚where Klausel ' Die SQL ausgeführt wurde war: SELECT * FROM 'Vorteile' WHERE (' product_has_advantage'.wichtig' = 1) UND ('ID' IN (' 1 ',' 2 ',' 4 ',' 14 ')) ORDER BY 'product_has_advantage''sort' DESC – rakete

+1

Siehe aktualisierte Antwort. – arogachev

+0

Warum ist das die akzeptierte Antwort? Ich habe das gleiche Problem (muss nach der in viattable definierten Tabelle sortieren) und das Verschieben der Spalten in die andere Tabelle ist nicht akzeptabel. – Scott

-2
public function getAdvantages() 
{ 
    return $this 
     ->hasMany(AdvantageModel::className(), ['id' => 'advantage']) 
     ->viaTable('product_has_advantage', ['product' => 'id']) 
     ->andWhere(['important' => 1]) 
     ->orderBy(['sort' => SORT_DESC]); 
} 
+1

Warum sollte das OP das "versuchen"? Eine ** gute Antwort ** wird immer eine Erklärung haben, was getan wurde und warum es so gemacht wurde, nicht nur für das OP, sondern auch für zukünftige Besucher von SO, die diese Frage finden und Ihre Antwort lesen können. –

0

Zuerst müssen Sie ein Modell ProductHasAdv für Verknüpfungstabelle (product_has_adv) mit CRUD genannt erstellen.

Dann Beziehung in product Modell erstellen und sortieren sie:

public function getAdvRels() 
    { 
     return $this->hasMany(ProductHasAdv::className(), ['product' => 'id'])-> 
     orderBy(['sort' => SORT_ASC]);; 
    } 

Dann zweite Beziehung wie folgt erstellen:

public function getAdvantages() 
{ 
    $adv_ids = []; 
    foreach ($this->advRels as $adv_rel) 
     $adv_ids[] = $adv_rel->advantage; 
    return $this->hasMany(Advantage::className(), ['id' => 'advantage'])->viaTable('product_has_adv', ['product' => 'id'])->orderBy([new Expression('FIELD (id, ' . implode(',', $adv_ids) . ')')]); 
} 

Dies wird Endergebnisses mit order by FIELD Technik sortieren.

Vergessen Sie nicht, hinzuzufügen:

use yii\db\Expression; 

Linie zu fahren.

2

Mit viaTable Methoden mit Beziehungen werden zwei getrennte Abfragen verursachen, aber wenn Sie Sie innerJoin auf folgende Weise nicht link() Verfahren benötigen können durch product_has_advantage Tabelle sortieren:

public function getAdvantages() 
{ 
    $query = AdvantageModel::find(); 
    $query->multiple = true; 
    $query->innerJoin('product_has_advantage','product_has_advantage.advantage = advantage.id'); 
    $query->andWhere(['product_has_advantage.product' => $this->id, 'product_has_advantage.important' => 1]); 
    $query->orderBy(['product_has_advantage.sort' => SORT_DESC]); 
    return $query; 
} 

Hinweis als $query->multiple = true ermöglicht es Ihnen, diese Methode als Yii2 hasMany Relation zu verwenden.

0

Für die, die nach einer Weile hierher kommen und die obigen Lösungen nicht mögen, habe ich es funktioniert, indem ich mich nach dem Filter via Tabelle wieder an die Via-Tabelle angeschlossen habe.

Beispiel für obigen Code:

public function getAdvantages() 
{ 
    return $this->hasMany(AdvantageModel::className(), ['id' => 'advantage']) 
     ->viaTable('product_has_advantage', ['product' => 'id']) 
     ->innerJoin('product_has_advantage','XXX') 
     ->orderBy('product_has_advantage.YYY'=> SORT_ASC); 
} 

kümmern sich um XXX mit dem rechten Join-Pfad und YYY mit der rechten Sortierspalte zu ändern.