如何检查两条记录是否具有自引用关系?

时间:2010-03-08 10:56:51

标签: php oop doctrine

与用户及其同事(朋友)一起考虑以下架构:

用户

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. Doctrine是否有任何预构建功能来检查具有自我关系的两条记录是否相关?
  2. 如果没有,你会怎么写一个方法来检查这个?
  3. 你会把所说的方法放在哪里? (在User-class,UserTable-class等中)
  4. 我可能会做这样的事情:

    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;
    }
    

    但这看起来既不高效又不漂亮。我觉得它应该已经解决,因为自我引用关系很好用。

    修改

    鉴于我们在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']);
    }
    

    这应该比第一个建议的方法更有效,但它仍然需要获取(并补充)比我想要的更多的记录。

1 个答案:

答案 0 :(得分: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';

我假设用户可以是“邀请”或“邀请者”,因此是AND OR AND构造。

你可以把它放在任何你想要的方法里面。