如何在Doctrine中删除自引用n:n关系?

时间:2009-09-06 09:28:02

标签: php doctrine

我想在Doctrine中代表两个用户之间的朋友关系。我能够创建这种关系,但我不知道删除它的最佳方法是什么。

我有以下架构:

User:
  columns:
    name: string(255)
  relations:
    Friends:
      class: User
      local: user1
      foreign: user2
      refClass: FriendReference
      equal: true

FriendReference:
    columns:
        user1:
            type: integer
            primary: true
        user2:
            type: integer
            primary: true    

以下是我创建关系的方式:

$user1 = new User();
$user2 = new User();
$user1->Friends[] = $user2;

这很有效。

mysql> select * from friend_reference;
+-------+-------+
| user1 | user2 |
+-------+-------+
|     4 |     5 |
+-------+-------+
1 row in set (0.01 sec)

如果我要删除关系的两个主键4和5,那么删除关系的最佳方法是什么?我可以

  1. 获取ID为4的对象并通过$user->Friends进行迭代,然后使用unlink删除此关系。
  2. 撰写以下查询

    $query = Doctrine_Query::create()
       ->delete('FriendReference')
       ->where('(user1=4 AND user2=5) OR (user2=4 AND user1=5)')
       ->execute();
    
  3. 我认为这两种选择既不优雅也不高效。

2 个答案:

答案 0 :(得分:0)

我会选择第二种选择。它不像第一个那么好,但迭代所有朋友删除一个似乎不是一个好主意。

答案 1 :(得分:0)

我可能会这样做:

class User extends Doctrine_Record {

   public function removeFriend (User $friend) {
      $this->getTable()->execute('remove.friend', 
         array('user1' => this->id, 'user2' => $friend->id));
   }
}

class UserTable extends Doctrine_Table {
   public function setUp () {
      $this->addNamedQuery('remove.friend',
         Doctrine_Query::create()
            ->delete('FriendReference')
            ->where('(user1=:user1 AND user2=:user2) 
                     OR (user2=:user1 AND user1=:user2)'
   }
}

//Some other place:
$user->removeFriend($noLongerMrNiceGuy);

您可以阅读有关删除n-m关系链接here的建议方法。摘自文档:

  

删除多对多关联记录之间链接的正确方法是使用DQL DELETE语句。使用DQL DELETE的方便和推荐的方法是通过查询API。

// test.php
$q = Doctrine_Query::create()
    ->delete('GroupUser')
    ->addWhere('user_id = ?', 5)
    ->whereIn('group_id', array(1, 2));
     

$ deleted = $ q-> execute();

     

解除相关对象之间关系的另一种方法是通过Doctrine_Record :: unlink方法。但是,除非您已经拥有父模型,否则应该避免使用此方法,因为它涉及首先查询数据库。