2016-12-10 4 views
0

Я делаю приложение для обмена сообщениями, и мне нужно проверить, существует ли уже разговор, который имеет определенный список пользователей (не более, не менее). У меня есть эта модель:Laravel получить разговор, где пользователи в массиве

class Conversation{ 
    public function users(){ 
     return $this->belongsToMany('App\User'); 
    } 
    public function messages(){ 
     return $this->hasMany('App\Message'); 
    } 

} 

У меня есть эти таблицы:

разговоры:

  • ID
  • user_id < - владелец разговора

пользователей:

  • ID
  • электронной
  • пароль

conversation_user:

  • ID
  • conversation_id
  • user_id

Я хочу сделать пост запрос, как это:

{ 
    "users": [1,4,6], <- user ids 
    "message": "Some message" 
} 

Если разговор уже существует со всеми и только для пользователей 1,4,6, сообщение должно быть добавлено к этому разговору, чтобы избежать повторяющихся разговоров в база данных. В противном случае я сделаю новый разговор с указанными пользователями. Это лучшее, что я был в состоянии сделать до сих пор:

$existing_conversation = $user->conversations()->whereHas('users', 
    function($query) use ($data){ 
     $query->whereIn('user_id', $data['users']); 
    } 
)->has('users', '=', count($data['users'])); 

Но это просто возвращает разговоры, что имеет именно количество пользователей, которые были в массиве пользователей. Он игнорирует внутренний запрос.

У кого-нибудь есть идея? :)

+0

Эй @Donkarnash. Это не имело никакого значения :( – Bisgaard

+0

Непонятно из представленного кода, кажется, что модели «Разговор и пользователь» разделяют отношение «многие ко многим» через сводную таблицу. В этом случае, как вы можете проверить user_id на разговоры?Пожалуйста, предоставьте таблицу и подробную информацию о модели пользователя и разговора для понимания вашей текущей структуры кода. – Donkarnash

+0

Привет, @Donkarnash. Ты буйный. Я редактировал вопрос, чтобы включить структуру таблицы. convers_user - сводная таблица. – Bisgaard

ответ

1

Вы можете попробовать следующий запрос

$existing_conversation = $user->conversations()->wherePivotIn('user_id', $data['users'])->has('users', count($data['users'])->get(); 

Не тестировался, должен работать, я думаю.

UPDATE

Не очень элегантное решение, однако оно работает. Вы можете добавить некоторые вспомогательные методы в контроллере, как

//Get user's conversations with no of users equal to count($data['users']); 
protected function get_conversations_with_equal_users(User $user, array $user_ids) 
{ 
    return $user->conversations() 
       ->wherePivotIn('user_id', $user_ids) 
       ->has('users', '=', count($user_ids)) 
       ->get(); 
} 

//Get the id of a user conversation with exactly same users as $data['users'] if it exists otherwise it will return 0; 
protected function get_existing_conversation_id(User $user, array $user_ids) 
{ 
    $existing_conversation_id = 0; 
    $user_conversations_with_equal_users = $this->get_conversations_with_equal_users($user, $user_ids); 

    foreach($user_conversations_with_equal_users as $conv) 
    { 
     $ids = []; 
     foreach($conv->users as $user) 
     { 
      $ids[] = $user->id; 
     } 
     if($this->array_equal($user_ids, $ids)) 
     { 
      $existing_conversation_id = $conv->id; 
     } 

    } 
    return $existing_conversation_id; 
} 

//Function to compare two arrays for equality. 
protected function array_equal($a, $b) { 
    return (
     is_array($a) && is_array($b) && 
     count($a) == count($b) && 
     array_diff($a, $b) === array_diff($b, $a) 
    ); 
} 

В общем, вы можете использовать следующие в контроллере, чтобы получить существующий разговор для пользователя (если она существует)

$existing_conversation_id = $this->get_existing_conversation_id($user, $data['users']); 
    if($existing_conversation_id) 
    { 
     $existing_conversation = Conversation::with('users') 
      ->whereId($existing_conversation_id) 
      ->get(); 
    } 
+0

Он просто возвращает разговоры с нужным количеством пользователей. – Bisgaard

+0

@Bisgaard Я отредактировал свой ответ с предложением о альтернативном подходе к тому, что вы пытаетесь выполнить - посмотрите. Он может работать на вас? – Donkarnash

+0

Причина, по которой я хочу найти разговоры с указанными пользователями, заключается в том, чтобы избежать дублирования разговоров в базе данных. У меня уже есть сообщение, относящееся к функциональности разговора. Я просто оставил его вне вопроса для простоты :) – Bisgaard

Смежные вопросы