Laravel Pivot Table, Get Room, принадлежащий пользователям - PullRequest
0 голосов
/ 02 марта 2020

Структура моей сводной таблицы:

room_id - user_id

У меня есть 2 пользователя в одной комнате.

Как я могу получить комнаты, которые у них обоих общие?

Было бы неплохо создать класс c, чтобы иметь что-то подобное.

Room::commonToUsers([1, 5]);

Потенциально Я мог бы проверить больше пользователей, поэтому логика c не должна ограничиваться определенным количеством пользователей.

Room::commonToUsers([1, 5, 6, 33, ...]);

Ответы [ 4 ]

1 голос
/ 02 марта 2020

Я создал проект Laravel и создал таблицы users, 'rooms', 'room_users' и их модели и определил функцию stati c в RoomUser Model следующим образом:

public static function commonToUsers($ids)
{
    $sql = 'SELECT room_id FROM room_users WHERE user_id IN (' . implode(',', $ids) . ') GROUP BY room_id HAVING COUNT(*) = ' . count($ids);
    $roomsIds = DB::select($sql);
    $roomsIds = array_map(function ($item){
        return $item->room_id;
    }, $roomsIds);
    return Room::whereIn('id', $roomsIds)->get();
}

В этом методе я использую self join, поскольку таблица объединяется сама с собой, A и B - это разные псевдонимы таблицы для одной и той же таблицы, затем я применил условие where между этими двумя таблицами (A и B). ) и работать на меня.

Надеюсь, будет полезным.

0 голосов
/ 02 марта 2020

Возможно, есть более эффективный способ, но в коллекции laravel есть метод intersect. Вы можете создать функцию stati c, которая извлекает и l oop через каждый объект и сохраняет только все пересекающиеся комнаты. как-то так

public static function commonToUsers($userArr){
  $users = User::whereIn('id',$userArr)->get();
  $rooms = null;

  foreach($users as $user){
    if($rooms === null){
      $rooms = $user->rooms;
    }else{
      $rooms = $rooms->intersect($user->rooms);
    }
  }

  return $rooms;
}

Этот код не проверен, но он должен работать.

0 голосов
/ 02 марта 2020

Room имеет много users, user имеет много rooms, поэтому вы можете найти room, в котором есть эти два users.

Если имя вашей сводной таблицы равно room_users, тогда вы можете легко получить общую комнату, как это:

public static function commonToUsers($user_ids) {
    $room = new Room();
    foreach($user_ids as $user_id) {
        $room->whereHas('users', function($query) use ($user_id) {
            $query->where('room_users.user_id', $user_id);
        });
    }
    return $room->get();
}

Этот код будет преобразован в raw sql:

select * 
from `rooms` 
where exists (
    select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 1
) 
and exists 
(
    select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 5
)
0 голосов
/ 02 марта 2020

Я не знаю названий ваших отношений, но, думаю, вы можете сделать так:

$usersIds = [1, 5];
$rooms = Room::whereHas('users', function($query) use ($usersIds) {
      foreach ($usersIds as $userId) {
          $query->where('users.id', $userId);
      }
})->get();

Это должно сработать. whereHas позволяет запросить ваше отношение. Если вам нужен метод stati c, вы можете добавить метод в вашу модель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...