У меня есть стол 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'), ); }
Есть идеи?
EDIT # 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'), ); }
У меня было то же самое, что и я, над чем я работал. Что я сделал, так это то, что я создал другую функцию для компиляции двух отношений в один массив. Причина этого заключается в том, что даже если вы должны были объединить два отношения, каждый раз, когда вам все равно нужно будет проверить, является ли PersonA или PersonB текущим идентификатором пользователя, и использовать другой идентификатор, чтобы вытащить информацию друзей. Вот функция, которую я создал в моей модели:
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();
Это решение работало для меня:
Переопределите функцию __get
в вашей модели:
public function __get($name) { if(($name == 'friends1') || ($name == 'friends2')) { return parent::__get('friends1') + parent::__get('friends2'); } else return parent::__get($name); }