Laravel ORM 友谊关系不重复

Posted

技术标签:

【中文标题】Laravel ORM 友谊关系不重复【英文标题】:Laravel ORM Friendship Relationship without duplication 【发布时间】:2013-07-24 18:10:02 【问题描述】:

与 eloquent 建立友谊关系的最佳方式是什么?我的表架构如下,我想定义一个关系,我可以在其中检索所有朋友,如下所示。

<?php

class User extends Eloquent 

public function friends() 
    return $this->belongsToMany('User', 'friendships', 'user_id', 'friend_id')->orWhere($this->id,'=', 'friend_id');
  


+----+---------+-----------+----------+---------------------+---------------------+
| id | user_id | friend_id | state    | created_at          | updated_at          |
+----+---------+-----------+----------+---------------------+---------------------+
|  1 |       3 |         1 | accepted | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|  2 |       2 |         3 | accepted | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----+---------+-----------+----------+---------------------+---------------------+

当我寻找用户 ID 为 3 的朋友时,上面的关系接近工作我得到用户 1 和 3,但显然我想要 1 和 2。

友谊表

user_id:请求友谊的用户 ID friend_id:目标好友的用户 ID state:友谊是挂起、接受还是阻止。 created_at 和 updated_at

我知道Laravel Many to many self referencing table only works one way 提供了一些解决方案,我可以在其中检索关系双方的朋友,但我必须是两行,例如如果用户 1 和 3 是朋友,那么在一行中 user_id = 3和friend_id = 1,在下一行反之亦然。 (或者如果我没有两行,我必须做两个查询)。

【问题讨论】:

【参考方案1】:

您可以进行两次查找,and use a union query,因此只访问数据库一次。将所有这些放在自定义函数中:

class User extends Eloquent 

  public function friends()
  
     $first = $this->belongsToMany('User', 'friendships', 'user_id', 'friend_id');  
     return $this->belongsToMany('User', 'friendships', 'friend_id', 'user_id')->union($first);  
  

【讨论】:

谢谢这看起来正是我想要的但是我得到了这个错误参数 1 传递给 Illuminate\Database\Query\Builder::mergeBindings() 必须是 Illuminate\Database\Query\Builder 的一个实例,给定的 Illuminate\Database\Eloquent\Relations\BelongsToMany 实例,在第 857 行的 /var/www/cc/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php 中调用并定义【参考方案2】:

我有一个建议,你可以使用条件来加载你想要的值

在这个例子中,假设你使用查询来加载 user_id 和 fiend_id 的条件,

" select * fromfriendship WHERE user_ID = '$id' ORfriend_ID = '$id' "

$id : 是你想给他的朋友看的用户ID。

在 PHP 中的 WHILE 循环中,您将使用它来加载结果,您可以通过设置条件来过滤结果

while ... 

if (friendship['user_id'] == $id) 

$f_id = friendship['friend_id'] ;  

// other instructionS...

else  

$f_id = friendship['user_id'] ;   

// other instructionS...


在这种情况下,您将从两个表列中加载数据,然后每次使用用户 id 过滤列,只让他的朋友的 id ,过滤器过去不会告诉用户您是自己的朋友。

对不起,我用mysql来解释例子

【讨论】:

我不确定如何在 Eloquent 中使用它?【参考方案3】:

您不应该尝试将应该是两行的内容变成一行,但如果您要尝试这样做,那么您绝对不需要两次访问数据库:

select * from users where (user_id = :user_id and friend_id = :friend_id) or  (friend_id = :friend_id and user_id = :user_id)

在 Laravel 中应该是:

Users::whereRaw('(user_id = ? and friend_id = ?) or (friend_id = ? and user_id = ?)', [            
    $user_id,
    $friend_id,
    $friend_id,
    $user_id
]);

您也可以使用 sub-where 来对它们进行分组,但这有点复杂。

【讨论】:

以上是关于Laravel ORM 友谊关系不重复的主要内容,如果未能解决你的问题,请参考以下文章

laravel orm更新文档[重复]

Laravel 4:如何使用 Eloquent ORM“排序”[重复]

是否可以根据 Laravel 的 ORM 中的多个列删除重复项?

与 Laravel 的友谊系统:多对多关系

Laravel 5.2 友谊系统:多对多关系

仅从 Laravel 5.2 关系查询中选择特定列不起作用 [重复]