2010-03-08 2 views
2

Рассмотрим следующую схему с пользователями и их коллег (друзей):Как проверить, имеет ли отношение двух записей отношение самореференции?

Пользователи

User: 
    columns: 
    user_id: 
     name: user_id as userId 
     type: integer(8) 
     unsigned: 1 
     primary: true 
     autoincrement: true 
    first_name: 
     name: first_name as firstName 
     type: string(45) 
     notnull: true 
    last_name: 
     name: last_name as lastName 
     type: string(45) 
     notnull: true 
    email: 
     type: string(45) 
     notnull: true 
     unique: true 
    relations: 
    Collegues: 
     class: User 
     local: invitor 
     foreign: invitee 
     refClass: CollegueStatus 
     equal: true 
     onDelete: CASCADE 
     onUpdate: CASCADE 

Регистрация таблице:

CollegueStatus: 
    columns: 
    invitor: 
     type: integer(8) 
     unsigned: 1 
     primary: true 
    invitee: 
     type: integer(8) 
     unsigned: 1 
     primary: true 
    status: 
     type: enum(8) 
     values: [pending, accepted, denied] 
     default: pending 
     notnull: true 

Теперь, скажем, я две записи, одна для решений пользователя HTTP-запрос (зарегистрированный пользователь) и одна запись для пользователя, которому он хочет отправить сообщение. Я хочу проверить, являются ли эти пользователи коллегами.

Вопросы:

  1. ли Доктрина есть какие-либо функции предварительной сборки, чтобы проверить, если две записи с связаны с автопортреты отношения?
  2. Если нет, как бы вы написали метод проверки этого?
  3. Куда вы поместите указанный метод? (В классе пользователей, UserTable-класс и т.д.)

Я мог бы сделать что-то вроде этого:

public function areCollegues (User $user1, User $user2) { 
    // Ensure we load collegues if $user1 was fetched with DQL that 
    // doesn't load this relation 
    $collegues = $user1->get('Collegues'); 
    $areCollegues = false; 
    foreach($collegues as $collegue) { 
     if($collegue['userId'] === $user2['userId']) { 
      $areCollegues = true; 
      break; 
     } 
    } 
    return $areCollegues; 
} 

Но это выглядит ни эффективным, ни достаточно. Я просто чувствую, что он должен быть решен уже для отношений с саморегуляцией, чтобы быть приятным в использовании.

EDIT:

Учитывая, что мы установили следующее UserTable::construct():

$this->setAttribute(Doctrine::ATTR_COLL_KEY, 'userId'); 

Тогда описанный выше метод, вероятно, может быть записано как:

public function areCollegues (User $user1, User $user2) { 
    // Ensure we load collegues if $user1 was fetched with DQL that 
    // doesn't load this relation 
    $collegues = $user1->get('Collegues'); 
    return isset($collegues[$user2['userId']); 
} 

Это должно быть более эффективным чем первый предложенный метод, но он все равно должен получать (и гидратировать) больше записей, чем хотелось бы.

+0

+1. Я сталкивался с этим раньше, и мне было бы интересно узнать, есть ли более хороший способ сделать это! – richsage

ответ

1

Возможно, это не то, что вам нужно, но почему бы не просто запросить таблицу? Это намного более эффективное:

$john = // invitor id 
$lisa = // invited id 
$q = Doctrine_Query::create() 
    ->select('c.invitor') 
    ->from('CollegueStatus c') 
    ->where('c.invitor = ? AND c.invited = ? OR c.invitor = ? AND c.invited = ?, array($john, $lisa, $lisa, $john)) 
    ->limit(1); 
$result = $q->execute(array(), Doctrine_Core::HYDRATE_NONE); 
if (!empty($result)) echo 'they are colleagues'; 

я предполагал, пользователь может быть либо «приглашен» или «приглашающий», следовательно, и или и построить.

И вы можете поместить это внутри метода в любом месте.

+0

+1. Да, это метод, который я использую в настоящее время, но я хотел посмотреть, существует ли это уже как метод, поскольку причина установки отношения самореференции в модели заключается в том, чтобы не вводить (col1 = x и col2 =) y OR (col1 = y и col2 = x). Вы можете просто сказать $ user-> Collegues, который, когда он получает отношение, автоматически добавляет правильное соединение или в DQL из («Пользователь u») -> innerJoin («u.Collegues c»), который также считает, что Значения col1 и col2 являются либо x, либо y. – PatrikAkerstrand

+0

Да, это всего лишь стоимость всей гидратации данных для тривиальной информации. – Tom

Смежные вопросы