Laravel 多重关系

Posted

技术标签:

【中文标题】Laravel 多重关系【英文标题】:Laravel multi relationship 【发布时间】:2021-11-26 17:20:04 【问题描述】:

我正在 laravel/vue 中开发聊天应用程序,在这个应用程序中,我有用户,每个用户有几个房间,每个房间至少有 2 个用户,并且我正在尝试建立关系或查询几条消息以获取所有每个用户的房间和其中的消息

Schema::create('users', function (Blueprint $table) 
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->enum('status',['active','busy','Do Not Disturb']);
        $table->timestamp('email_verified_at')->nullable();
        $table->string('image')->default('user0.jpg');
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    );

Schema::create('rooms', function (Blueprint $table) 
        $table->id();
        $table->string('room_unique');
        $table->foreignId('user_id')->constrained()->onDelete('cascade')->onUpdate('cascade');
        $table->timestamps();
    );
Schema::create('messages', function (Blueprint $table) 
        $table->id();
        $table->enum('type',['text','image','link']);
        $table->string('content');
        $table->foreignId('user_id')->constrained()->onDelete('cascade')->onUpdate('cascade');
        $table->foreignId('room_id')->constrained()->onDelete('cascade')->onUpdate('cascade');
        $table->timestamps();
    );

【问题讨论】:

【参考方案1】:

你所拥有的是好的。我只需从房间中取出外键user_id 并通过他们的消息访问用户的房间。因此,messages 就像一个数据透视表,使用户和房间之间的关系成为多对多关系。

因此我会访问用户的房间

$rooms = User::find(1)->rooms()->get();

访问房间中的用户

$users = Room::find(1)->users()->get();

在每个房间显示用户的消息就像访问数据透视表一样。因此

$user = User::find(1);

foreach ($user->rooms as $rooms) 
    echo $rooms->pivot->content;


所以,这是多对多的关系,而消息是数据透视表。我会坚持documentation for more details.

【讨论】:

如果我们有很多房间供用户使用,我们将有一个 $user->rooms 的 foreach 作为 $room,一个 $room->messages 的 foreach 作为 $message,或每个用户按 room_id。 是的,我们可以为每个用户提供多个房间。这就是为什么我查询一位用户并获取该用户所在的所有房间的原因。然后按照您的建议继续 for 循环。此外,每个房间中有多个消息,但它们都属于一个用户,而不是房间。因此,您使用$rooms->pivot->content$users->pivot->content 获取消息 我们应该已经知道了,这里肯定是拥有房间用户的所有消息,或者只是房间中活跃用户的消息的问题,因为它不是 HasManyThrough拥有用户通过房间的所有消息,您应该已经知道,这里肯定是拥有房间用户的所有消息的问题,而不仅仅是相关用户的消息,因为它不是 HasManyThrough,我们将收到来自所有用户的消息。在我看来,我们将收到房间内所有用户的消息,我认为这是正确的方式,还是什么?【参考方案2】:

我发现的最佳解决方案是建立这样的复杂关系 //关系

public function message() 

    return $this->hasMany(messages::class)->take(1);


public function friends()

    return $this->belongsToMany(User::class, 'friends', 'user_id', 'friend_id');


public function rooms()

    return $this->belongsToMany(Room::class,'user_room','user_id','room_id');


public static function getInit()

    //get room of auth user
    $rooms =   DB::table('user_room')->where('user_id',Auth::id())->select('room_id')->get()->toArray();

    //flatten the array
    $roomArray = array_column(json_decode(json_encode($rooms), true),'room_id');

    //get users friends and rooms belong to auth user with the last message 
    $user = User::with(array('friends.rooms' => function($query) use ($roomArray)
                $query->whereIn('rooms.id',$roomArray);
            ,'friends.rooms.messages' => function($query) 
                $query->orderBy('created_at','Desc');
            ))->whereId(Auth::id())->get()->toArray();
    return $user;

在 getinit 中,我只是像 (friends.rooms) 一样使用这种关系

laravel 将使用好友关系,然后每个结果都将使用房间关系,在我的情况下,我只需要选择用户和好友拥有的房间,所以我通过使用房间中属于身份验证用户的位置来限制关系,就像我们说的那样auth 用户有房间 2,3,4,他的朋友有 3,1,5 所以房间关系只会返回 auth 用户房间和朋友房间的联合,在我们的例子中是 3 然后我在每个房间返回消息,但用于设计目的我只需要每个房间的最后一条消息,所以我将我的关系消息限制为 1,并在 getinit 中按创建日期 desc 对它们进行排序

【讨论】:

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

求和列的 Laravel 多重关系

Laravel中的多重关系(枢轴)

Laravel中多对多关系的多重搜索子句

Laravel:Eloquent模型中的多重多态关系

Laravel-数据表内联编辑和使用多重自动完成功能

Laravel 关系,hasmany 和 blongstomany