我有一个表Friend (PersonA, PersonB)
。这些是Person(id, name)
的外键。
我想在他们之间建立一种Yii关系。这就是我想到的:
public function relations() {
return array(
'friends1' => array(self::HAS_MANY, 'Friend', 'PersonA'),
'friends2' => array(self::HAS_MANY, 'Friend', 'PersonB'),
);
}
有没有办法把这两种关系结合起来?我希望有这样的东西:
public function relations() {
return array(
'allFriends' => array(self::HAS_MANY, 'Friend', 'PersonA, PersonB'),
);
}
有什么想法吗?
编辑#1:
为了完整起见,我们还假设我想订购friends1
和friends2
,如下所示:
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'),
);
}
这个解决方案对我有效:
覆盖模型中的__get
功能:
public function __get($name)
{
if(($name == 'friends1') || ($name == 'friends2')) {
return parent::__get('friends1') + parent::__get('friends2');
}
else
return parent::__get($name);
}
我在做的事情中遇到了完全相同的事情。我所做的是创建了另一个函数,将这两个关系编译成一个数组。原因是,即使你将这两种关系结合在一起,每次你仍然需要测试PersonA或PersonB是否是当前用户的id,并使用另一个id来获取好友信息。以下是我在模型中创建的函数:
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;
}
另一种选择:
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;
}
那么对于任何人,你都可以说:
$person = Person::model()->findByPk(1);
$friends = $person->friends;
或者,您可以发送回一个CActiveDataProvider
,而不是一个数组,您可以使用它进行排序和其他操作。你可以这样做:
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,
));
}
然后,由于您有CActiveDataProvider,您可以排序:
$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();