问题
我为我的 Laravel 应用程序创建了一个简单的友谊关系,一切正常,直到我注意到当我查询用户的友谊时,它只会在 UID1
字段上搜索当前用户。
由于友谊本质上是一种双向关系,我试图在 Laravel 模型中找到一种方法来通过多列检索所有友谊关系。
当前实现
public function friends()
{
return $this->belongsToMany( App\Modules\Users\Models\User::class ,'friends', 'uid1');
}
理想的实现
public function friends()
{
$a = $this->belongsToMany( App\Modules\Users\Models\User::class ,'users_friends', 'uid1');
$b = $this->belongsToMany( App\Modules\Users\Models\User::class ,'users_friends', 'uid2');
return combine($a,$b);
}
表结构
+----------------------+
| users table |
+----------------------+
+----| id: primary UserID |
| | fname: string |
| +----------------------+
|
|
| +----------------------+
| | friends table |
| +----------------------+
| | id: primary iD |
| | |
+----| uid1: user_id |
| | |
+----| uid2: user_id |
+----------------------+
如果当前用户 ID = 1(根据下面的好友表中的数据),当前的实现将仅导致返回其中 1 条记录。
+-------------------------------+
| friends table (data) |
+--------|---------|------------+
| id | uid1 | uid2 |
+--------|---------|------------+
| 1 | 1 | 7 |
| 2 | 7 | 1 |
| 3 | 9 | 1 |
+-------------------------------+
用户模型
<?php
namespace App\Modules\Users\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
protected $fillable = [
'username', 'email', 'password', .... .
];
public function friends()
{
return $this->belongsToMany( App\Modules\Users\Models\User::class ,'users_friends', 'uid1');
}
环境
- 服务器 = Homestead/linux
- PHP = 7
- MySQL
更新
我创建了一个 Friendship 帮助器类,它执行类似的操作,但是在这个函数中我显式传入了 UserID
Friendship::where( [
[ 'uid1' ,'=', $uid],
])->orWhere( [
[ 'uid2', '=', $uid]
])->all();
最佳答案
在声明关系时,您可以通过简单地链接关系来添加其他条件。
<?php
//...
class User extends Model {
//...
public function friends() {
return $this->hasMany(/*...*/)->orWhere('uid2', $this->id);
}
//...
但请记住,eloquent 不会将关系的第一个条件分组在括号中,因此您可能会以在某些情况下无法按预期工作的 SQL 结束(如果使用 or、and 应该没问题)
例如,上面的代码可能会生成如下所示的 SQL
SELECT * FROM users_friends WHERE uid1 = ? AND uid1 IS NOT NULL OR uid2 = ?
这是一个正确的 SQL 语句,但如果不进行分组,您将无法得到您期望的结果。
另一种方法是使用accessor和两个独立的关系
<?php
//...
public function friends1() {
return $this->belongsToMany(User::class, 'users_friends', 'uid1');
}
public function friends2() {
return $this->belongsToMany(User::class, 'users_friends', 'uid2');
}
public function getFriendsAttribute() {
return $this->friends1->merge($this->friends2);
}
//...
但是这样您就可以两次单独前往数据库。
关于php - Laravel 5.5 用户模型和好友关系(belongsToMany)由多列组成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46313538/