2016-12-10 3 views
0

Ich mache eine Messaging-App, und ich muss überprüfen, ob eine Konversation bereits existiert, die eine bestimmte Liste von Benutzern hat (nicht mehr und nicht weniger). Ich habe dieses Modell:Laravel bekommen Konversation, wo Benutzer in Array

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

} 

Ich habe diese Tabellen:

Gespräche:

  • id
  • < user_id - der Besitzer des Gesprächs

Benutzer:

  • id
  • E-Mail
  • Passwort

conversation_user:

  • id
  • conversation_id
  • User_id

Ich möchte eine Post-Anforderung wie folgt machen:

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

Wenn ein Gespräch bereits mit allen und nur Benutzer 1,4,6 vorhanden ist, sollte die Nachricht an diesem Gespräch hinzugefügt werden doppelte Gespräche in der zu vermeiden, Datenbank. Ansonsten werde ich eine neue Konversation mit den angegebenen Benutzern führen. Dies ist die beste ich in der Lage gewesen, so weit zu tun:

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

Aber es gibt nur die Gespräche, die genau die Menge an Benutzern, die in der Benutzer-Array war. Es ignoriert die innere Abfrage.

Hat jemand eine Idee dafür? :)

+0

Hey @Donkarnash. Das hat keinen Unterschied gemacht :( – Bisgaard

+0

Es ist unklar, aus dem Code zur Verfügung gestellt, es scheint, dass Conversation und User-Modelle Many-to-Many-Beziehung durch eine Pivot-Tabelle teilen. In diesem Fall, wie können Sie nach user_id auf überprüfen Gespräche?Bitte geben Sie die Tabelle und Modelldetails von Benutzer und Konversation an, um Ihre aktuelle Codestruktur zu verstehen. – Donkarnash

+0

Hey @Donkarnash. Sie sind richtig. Ich habe die Frage bearbeitet, um die Tabellenstruktur einzuschließen. conversation_user ist eine Pivot-Tabelle. – Bisgaard

Antwort

1

Sie können versuchen, die folgende Abfrage

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

nicht getestet, sollte ich denken, arbeiten.

UPDATE

Nicht eine sehr elegante Lösung, aber es funktioniert. Sie können wie

//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) 
    ); 
} 

Die einige Hilfsmethoden in Ihrem Controller fügen Sie die folgenden in Ihrem Controller verwenden können, das bestehende Gespräch für Benutzer zu erhalten (falls vorhanden)

$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

Es gibt nur die Konversationen mit der richtigen Anzahl von Benutzern zurück. – Bisgaard

+0

@Bisgaard Ich habe meine Antwort mit einem Vorschlag für eine alternative Herangehensweise an das, was Sie erreichen wollen, bearbeitet - sehen Sie sich um. Kann es für dich arbeiten? – Donkarnash

+0

Der Grund, warum ich die Konversationen mit den angegebenen Benutzern finden möchte, besteht darin, doppelte Konversationen in der Datenbank zu vermeiden. Ich habe bereits die Nachricht gehört Konversation Funktionalität .. Ich habe es einfach aus Gründen der Einfachheit ausgeschlossen :) – Bisgaard