4

次のように定義されたいくつかの関係を持つモデルがあります。

public function relations()
{
    return array(
        'linkingTable' => array(self::HAS_MANY, 'LinkingTable', array('this_id'=>'id'), 'scopes'=>array('valid')),
        'linkedItems' => array(self::HAS_MANY, 'LinkedItem', array('linked_item_id'=>'id'), 'through'=>'linkingTable', 'scopes'=>array('valid')),
    );
}

リンク テーブルとリンクされたアイテムの両方に有効なスコープがあります。

public function scopes() {
    return array(
        'valid'=>array(
            'condition'=>"t.`valid`=1",
        ),
    );
}

生成された結合クエリがリレーション スコープで機能するためには、次のようにスコープを変更する必要がありました。

public function scopes() {
    return array(
        'valid'=>array(
            'condition'=>"`linkingTable`.`valid`=1",
        ),
    );
}

と:

public function scopes() {
    return array(
        'valid'=>array(
            'condition'=>"`linkedItems`.`valid`=1",
        ),
    );
}

問題は、リンクされたモデルから直接使用すると、これらのスコープが機能しないことです。つまり、次のようになります。

$linkedItems = LinkedItem::model()->valid()->findAll();

linkedItemsエイリアスが定義されていないことを示すエラーが発生します。もちろん、これは理解できます。また、まったく同じ方法で関係を定義する必要があるいくつかの LinkedItems を所有したい他のモデルが必要になります。

次のように、ユース ケースごとに異なるスコープを定義する唯一のソリューションです。

public function scopes() {
    return array(
        'valid'=>array(
            'condition'=>"t.`valid`=1",
        ),
        'validForModelRelation'=>array(
            'condition'=>"`linkedItems`.`valid`=1",
        )
    );
}

これはちょっとゴツい気がします。これを行うより良い方法があるかどうか疑問に思っていますか?

4

2 に答える 2

6

テーブルの現在のエイリアスを取得できる必要があります。t単独の場合はリレーション名、関連モデルの場合はリレーション名。関連モデルの範囲内で使用できるもの:

public function scopes() {
    return array(
        'valid'=>array(
            'condition'=>$this->tableAlias.".`valid`=1",
        ),
    );
}

ただし、で使用する場合は、エイリアスを見つけようとして、無限ループを防ぐためにパラメーターとしてdefaultScope使用する必要があります。$this->getTableAlias(false, false).

編集:ドットがありません

于 2012-09-07T09:15:58.027 に答える
0

valid'condition'=>$this->tableAlias.". =1"の前に DOT が必要です。

于 2013-06-07T09:35:50.320 に答える