How Do I Refer To The Table Alias Of A Relation In Its "on" Property

Consider this relation in some model MyModel:


public function relations() {

  return array(

    myRelation=>array(self::HAS_ONE, 'OtherModel', 'myModel_id',

     'on'=>'myRelation.someField=whatever' // HOW DO I NAME myRelation table alias in a generic way?<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/huh.gif' class='bbc_emoticon' alt='???' />

    )

  )

}

Normally, in order to mention the OtherModel table in the on condition, I would use "myRelation" as the table alias, as that is the default alias.

However, if this relation is used with another on-the-fly custom alias, that won’t work anymore:

MyModel::model()->with(‘myRelation’=>array(‘alias’=>‘myCustomAlias’))->…

This will break the on condition above.

How do you get the table alias in that context? Obviously CActiveRecord::getTableAlias() doesn’t help here.

Hi matteosistisette,

Well, I had the same problem.

I think there’s no way to set the table alias in a generic way in “relations” method.

One workaround may be setting "on" on the fly:




MyModel::model()->with('myRelation'=>array(

   'alias'=>'myCustomAlias',

   'on'=>'myCustomAlias.someField = something'

))->....



And, another workaround may be specifying "scope" in the model of the relation.




// in OtherModel.php

public function scopes()

{

    return array(

        'foo' => array(

             'on' => $this->tableAlias . '.someField = t.otherField',

        ),

    );

}


// in MyModel

public function relations()

{

    return array(

        'bar' => array(self::HAS_ONE, 'OtherModel', 'my_model_id', 

            'scopes' => array('foo'),

        ),

        ...

    );

}



Not tested, but I hope it works.

Wow, really?

If there’s no way to do this, then it’s definitely a feature that is missing.

Having to do that every time you use the relation would be terrible.

I don’t think that would work. $this->tableAlias() would be evaluated when the “scopes()” method is called. I don’t think that’s when the scope is applied. Or is it?

Anyway, you can define the scope as a method; that is the workaround I currently use, but it’s awful, I was hoping there was a better solution :( I still have to explicitly include the scope every time I use the relation :(:frowning:

Hmm, as I said, I didn’t test it. Gonna test it and report back. :)

I have tested it and it worked.

"$this->tableAlias" was replaced not with the relation name but with the alias that has been set on the fly.

(My test case is not "on" but "condition", though.)

Would you please test it yourself?

That’s cool, I’ll test it.

However, how do you refer to the table alias on-the-fly.

Such as:


ModelA::model()->with(array('relatedModelB'=>array('condition'=>/*NEED THE TABLE ALIAS OF MODEL B HERE*/)))->findAll();

You need to create a named scope just to use it only once?

I would write as the following:




// using default table alias

ModelA::model()->with(array(

    'relatedModelB'=>array(

        'condition'=>'relatedModelB.some_field = some_value',

    )

))->findAll();


// or using custom table alias

ModelA::model()->with(array(

    'relatedModelB'=>array(

        'alias'=>'rb',

        'condition'=>'rb.some_field = some_value',

    )

))->findAll();



Sorry, but I don’t understand what you mean by that. Could you elaborate it a bit?