Yii - using relations with scopes defined in the r

2019-03-30 09:45发布

I have a model with some relations defined as follows.

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')),
    );
}

Both the linking table and the linked items have a valid scope:

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

In order for the generated join queries to work with the relation scope, I have had to modify the scopes as follows:

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

and:

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

The problem is that those scopes will not work when used from the linked model directly, i.e.:

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

Results in an error to say that linkedItems isn't a defined alias. Which is understandable, of course. It also results in a need for any other model who wants to own some LinkedItems needing to define the relation in the exact same way.

Is the only solution to define a different scope for each use case, like this:

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

This feels a bit cludgey. I am wondering if there is a better way of doing this?

标签: php yii
2条回答
Deceive 欺骗
2楼-- · 2019-03-30 10:27

You need a DOT before 'condition'=>$this->tableAlias.".valid=1",

查看更多
Lonely孤独者°
3楼-- · 2019-03-30 10:43

You need to be able to get the current alias of the table. t when it's alone, or the relation name when it's a related model. In the scope of the related model you can use:

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

If you use it in the defaultScope however, you need to use $this->getTableAlias(false, false). as the parameters to prevent an infinite loop, trying to find the alias.

edit: dot missing

查看更多
登录 后发表回答