Conditional relation?

I have a database of horses that have offspring. I want to setup a relation to find a horse’s offspring, but that depends on the horse’s gender (i.e. if male, check for all horses with this horse’s id as their father, if female, check for all horses with this horse’s id as their mother).

I know I can setup a relation of offspring, but how do I set it up so that the field it checks for is conditional on the gender?

Rough guess: Two classes inheriting from a parent class Horse using different default scope?


you can try like that:

'offspring' => array(self::HAS_MANY, 'Horse', ($this->gender=='m')?'father_id':'mother_id'),

If the horse is male, check the filed ‘father_id’, otherways ‘mother_id’.

I don’t think this will work, because relations are parsed once in __construct() method.

I can suggest to create two relations (offspringMale and offspringFemale) and a method called getOffspring() with the following contents:

return ($this->gender == 'm') ? $this->offspringMale : $this->offspringFemale;

this is how I solved my issue with general information being linked to specific home inspection data (data that is different from other inspection types).

In DarkNSF’s solution you won’t be able to use eager loading, whereas the other way you will be able to do that (just by loading both relations):


Yes, that’s true, but looks like equestrianerd doesn’t need to load all horses with all their offsprings.

Actually there is a the better solution - create two classes: HorseMale and HorseFemale, both inherit class Horse, but have different relations. Then overrride Horse’s instantiate method:

protected function instantiate($attributes)


    $class = ($attributes['gender'] == 'm') ? 'HorseMale' : 'HorseFemale';

    $model = new $class(null);

    return $model;


Now you can use Horse::model()->findAll() to retrieve models, but some models will be of HorseMale class, and some of HorseFemale. To load all models with their offspring eagerly you can separately load males and females.