首页 文章

Laravel 5.5用户模型和朋友关系(belongsToMany)由多列组成

提问于
浏览
0

问题

我为我的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      |
     +----------------------+

根据下面的friends表中的数据,当前UserID = 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');

    }

环境

  • Server = Homestead / linux

  • PHP = 7

  • MySQL

更新

我有一个我创建的FriendShip助手类,它做了类似的事情,但是在这个函数中我明确地传递了UserID

Friendship::where( [
                    [ 'uid1' ,'=', $uid],
                ])->orWhere( [
                    [ 'uid2', '=', $uid]
                ])->all();

1 回答

  • 0

    您可以通过简单地链接来声明关系时添加其他条件 .

    <?php
    //...
    class User extends Model {
    //...
        public function friends() {
            return $this->hasMany(/*...*/)->orWhere('uid2', $this->id);
        }
    //...
    

    但请记住,eloquent不会在括号中对关系的第一个条件进行分组,因此您可能会以某些情况下无法正常工作的SQL结束(如果使用 orand 应该没问题)

    例如,上面的结果可能会导致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);
    }
    //...
    

    但是这样你就可以两次单独前往DB .

相关问题