Reputation: 1469
I have a table Friend (PersonA, PersonB)
. These are foreign keys of Person(id, name)
.
I want to create a Yii relation between them. This is what I have come up with:
public function relations() {
return array(
'friends1' => array(self::HAS_MANY, 'Friend', 'PersonA'),
'friends2' => array(self::HAS_MANY, 'Friend', 'PersonB'),
);
}
Is there a way to combine these two relations into one? I was hoping for something like this:
public function relations() {
return array(
'allFriends' => array(self::HAS_MANY, 'Friend', 'PersonA, PersonB'),
);
}
Any ideas?
EDIT #1:
For completeness, let's also imagine that I want to order friends1
and friends2
like this:
public function relations() {
return array(
'friends1' => array(self::HAS_MANY, 'Friend', 'PersonA', 'order'=>'id ASC'),
'friends2' => array(self::HAS_MANY, 'Friend', 'PersonB', 'order'=>'id ASC'),
);
}
Upvotes: 0
Views: 1889
Reputation: 3949
This solution worked for me :
Override the __get
function in your model:
public function __get($name)
{
if(($name == 'friends1') || ($name == 'friends2')) {
return parent::__get('friends1') + parent::__get('friends2');
}
else
return parent::__get($name);
}
Upvotes: 1
Reputation: 7556
I had the exact same thing come up in something I was working on. What I did is I created another function to compile the two relations into one array. The reason for this is because even if you were to get the two relationships combined, each time you would still need to test to see if PersonA or PersonB is the current user's id and use the other id to pull the Friends info. Here is the function I created in my model:
public function getFriends() {
$all_friends = array();
foreach($this->friends1 as $friend) {
if($friend->PersonA == $this->id) {
$all_friends[] = $friend->PersonA;
} else {
$all_friends[] = $friend->PersonB;
}
}
foreach($this->friends2 as $friend) {
if($friend->PersonA != $this->id) {
$all_friends[] = $friend->PersonA;
} else {
$all_friends[] = $friend->PersonB;
}
}
return $all_friends;
}
Another options:
public function getFriends() {
$criteria = new CDbCriteria;
$criteria->compare('PersonA',$this->id);
$criteria2 = new CDbCriteria;
$criteria2->compare('PersonB',$this->id);
$criteria->mergeWith($criteria2,'OR');
$friends = Challenge::model()->findAll($criteria);
return $friends;
}
Then for any Person you can just say:
$person = Person::model()->findByPk(1);
$friends = $person->friends;
Or instead of an array you could send back an CActiveDataProvider
that you could do sorts and other things with. You could do this:
public function getFriends() {
$criteria = new CDbCriteria;
$criteria->compare('PersonA',$this->id);
$criteria2 = new CDbCriteria;
$criteria2->compare('PersonB',$this->id);
$criteria->mergeWith($criteria2,'OR');
return new CActiveDataProvider('Friend', array(
'criteria' => $criteria,
));
}
Then since you have CActiveDataProvider you can sort:
$friends = $user->friends->getData(); //not sorted or anything
//or you can manipulate the CActiveDataprovider
$data = $user->friends;
$data->setSort(array(
'defaultOrder'=>'PersonA ASC',
));
$friends = $data->getData();
Upvotes: 0