2012-08-15 2 views
5

Ich kann nicht zu viel Dokumentation über die Anwendung eines Standardbereichs auf ein Modell in yii finden, ich fragte mich, ob jemand mir erklären oder in die richtige Richtung zeigen könnte.Anwenden eines Standardbereichs mit Bezug auf eine Beziehung in yii

Die schnelle Version meiner Frage:

Ist es möglich, eine Beziehung zu einem Standardbereich hinzuzufügen, oder ‚mit‘ Kriterien standardmäßig jede AR-Suche auf einem Modell hinzufügen?

Die lange Version meiner Frage:

Eine kurze Zusammenfassung meiner App:

Ich habe zwei Modelle, provider und item. Welche haben eine m: 1-Beziehung, wo ein Anbieter viele Artikel haben kann, aber jeder Artikel kann nur einen Anbieter haben.

Bisher habe ich diese Beziehungen:

class Provider extends CActiveRecord 
{ 
    ... 
    public function relations() 
    { 
     return array(
      'items' => array(self::HAS_MANY, 'Item', 'id_provider', 'order'=>'rank DESC'), 
     ); 
    } 
    ... 
} 

class Item extends CActiveRecord 
{ 
    ... 
    public function relations() 
    { 
     return array(
      'provider' => array(self::BELONGS_TO, 'Provider', 'id_provider'), 
     ); 
    } 
    ... 
} 

In meinem Artikel Modell habe ich habe bereits eine defaultScope, die alle Offline-Elemente filtert (dh zeigt nur Gegenstände, die auf offline = false gesetzt sind):

Was ich jetzt tun möchte, ist auch filtern Sie Elemente, deren Anbieter offline gesetzt ist (dh nur Elemente zeigen, wo provider.offline = false neben der aktuellen item.offline = false).

Ich habe versucht, die Provider-Tabelle in der defaultScope Beitritt:

public function defaultScope() 
{ 
    $alias = $this->getTableAlias(false,false); 
    return array(
     'join'=>"JOIN `provider` AS `provider` ON `provider`.`id` = `$alias`.`id_provider`", 
     'condition'=>"`$alias`.`offline` = false AND `provider`.`offline` = false", 
    ); 
} 

jedoch das JOIN gilt nach der Anweisung ON, und causese einen Fehler (CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'provider.offline' in 'on clause').

ich auch versucht habe, einen mit Kriterien zum defaultScope Zugabe:

public function defaultScope() 
{ 
    $alias = $this->getTableAlias(false,false); 
    return array(
     'with'=>"provider", 
     'condition'=>"`$alias`.`offline` = false AND `provider`.`offline` = false", 
    ); 
} 

Aber ich bekomme den gleichen Fehler: SQLSTATE [42S22]: Column nicht gefunden: 1054 Unknown column 'provider.offline' in ' auf Klausel ").

Irgendwelche Vorschläge?

Antwort

6

Es gibt ein paar Dinge, die ich würde versuchen:

Zuerst Ihr Zustand ändern, um die ganze Sache gelten (und vergessen Sie nicht, dass, wenn es keine Elemente für einen Anbieter sind, wird es nicht den Anbieter zurückgeben

)
public function defaultScope() 
{ 
    return array(
     'with'=> array("provider" => array(
      'condition'=> "t.offline = false AND provider.offline = false", 
     ) 
    ); 
} 

Zweitens versuchen Bereiche auf Ihre Modelle hinzufügen und verweisen sie dann im Standardbereich wie folgt:

public function defaultScope() 
{ 
    return array(
     'scopes'=> array('default'), 
    ); 
} 

class Provider extends CActiveRecord 
{ 
    ... 
    public function scopes() 
    { 
     ... 
    } 
    ... 
} 

class Item extends CActiveRecord 
{ 
    ... 
    public function scopes() 
    { 
     ... 
    } 
    ... 
} 
+0

Natürlich ! Ich habe die Bedingung in die Hauptbedingung "Bedingung" gestellt, nicht in das "mit". Dein erster Vorschlag funktioniert perfekt, danke! – Stu

0

Gerade hatte ein ähnliches Problem. Während Benjamins erster Vorschlag mich in die richtige Richtung wies (sehr geschätzt!), Stieß ich auf ein unerwartetes Problem mit "Bedingung" und "mit", was vielleicht hilfreich sein könnte.

Wenn die Tabelle, der Sie beitreten (im Beispiel 'Provider') ein eigenes defaultScope hat, wird dies als Teil der SQL ON-Klausel angewendet, wenn Sie 'with' verwenden und die zurückgegebenen Zeilen einschränken.

Da ein Outer-Join verwendet wird, erhalten Sie immer noch einen Datensatz für jede Zeile in der Primärtabelle ('Element'), aber die 'Provider'-Felder können für einige Zeilen null sein, wenn defaultScope des Providers diese Zeilen verhindert ist zurückgekommen.

Dies verursacht kein Problem, bis Sie versuchen, eine Bedingung mit einem dieser Anbieterfelder anzuwenden. Dies geschieht als Teil der WHERE-Klausel, die nach dem Join verarbeitet wird. Da dieses Feld jedoch null ist, schlägt die Bedingung fehl und der Datensatz wird nicht zurückgegeben.

In einigen Fällen ist dies das gewünschte Verhalten sein, aber in anderen Fällen müssen Sie möglicherweise die Tests der ‚Anbieter‘ Felder innerhalb der Join mithilfe der on Option verschieben möchten:

public function defaultScope() 
{ 
return array(
    'with'=> array("provider" => array(
     'condition'=> "t.offline = false", 
     'on'=>"provider.offline = false", 
    ) 
); 
}