MySQL Update oder fügen Sie mehrere Zeilen ein - Raw Laravel SQL

MySQL Update oder fügen Sie mehrere Zeilen ein - Raw Laravel SQL

Problem

Ich habe Nachrichten im System zwischen mehreren Personen als Gruppenchat gesendet. Jedes Mal, wenn jemand zu Ladenachrichten geht (öffnet seinen Posteingang), muss ich diese Nachrichten wie gelesen markieren lassen. Ich habe kein eloquentes Modell für die Direct_Message_Read_at Pivot -Tabelle, und ich verwende eine Klasse, die die DB Laravel -Klasse zusammenfasst, um benutzerdefinierte MySQL -Abfrage zu schreiben, um dies zu tun.

Mein Problem ist, wie ich doppelte Einträge verhindern kann, wenn jemand den Meldungsthread 10 Mal öffnet und die Änderung des TimestAMP von Updatated_at jedes Mal ändert, wenn er die Nachricht lesen? (Da sie mehrmals denselben Nachrichten -Thread öffnen)

Lösung

Um die Einrichtung dieser Lösung zu unterstützen, zeigen wir zunächst, wie wir diese Tabelle mit Laravel -Migration erstellen:

Vor dem Drehpunkt erstellen wir eine Meldungstabelle, um alle Nachrichten von Personen zu speichern. Danach erstellen wir die Pivot -Tabelle.

Schema :: Create ('Direct_Message_Read_at', Funktion (Blueprint $ Tabelle)
$ table-> inkremente ('id');
$ table-> Integer ('message_id')-> unsigned ()-> nullable ();
$ table-> fremd ('message_id')-> referenzen ('id')-> on ('Direct_Messages')-> Ondelete ('Cascade');
$ table-> Integer ('user_id')-> unsigned ()-> nullable ();
$ table-> fremd ('user_id')-> referenzen ('id')-> on ('user')-> ondelete ('kaskade');
$ table-> Integer ('organisation_id')-> unsigned ()-> nullable ();
$ table-> fremd ('organisation_id')-> referenzen ('id')-> on ('organisations')-> ontdelete ('cascade');
$ table-> timestemps ();
$ table-> eindeutig (['message_id', 'user_id', 'organisation_id']); // das ist wirklich wichtig für
Verhindern Sie doppelte Einträge derselben Person
);

Jetzt möchten wir ein Ereignis und einen Hörer erstellen, der die geladenen Nachrichten verarbeitet.

Stellen Sie sich vor, Sie haben eine Klasse, die für das Laden aller Ihre Nachrichten verantwortlich ist (wenn Sie Ihren Posteingang öffnen)

öffentliche Funktion loadMessages ()

$ thread_messages = DirectMessage :: All ();
$ message_ids = $ this-> removemymessages ($ thread_messages)
Ereignis (New MessageRead ($ message_ids));

geschützte Funktion removemymessages ($ messages)

$ message_ids = [];
// Filtern Sie einfach alle Nachrichten heraus, die von Ihnen mit 'WO (' SENTER_ID 'gesendet werden,
Auth ()-> user ()-> id)-Verwenden Sie dies dazu Ihre eigene Codelogik
$ message_ids zurückgeben;

Jetzt im Messagesread können Sie diese definieren und an den Hörer weitergeben

Klassenmessagesread

Verwenden Sie Versand, Interactswithsockets, serializesModels;
public $ messages_ids = [], $ user_id, $ organisation_id;
/**
* Erstellen Sie eine neue Ereignisinstanz.
*
* @return void
*/
Öffentliche Funktion __construct ($ message_ids = [])

$ this-> message_ids = $ message_ids;
$ this-> user_id = auth ()-> user ()-> id;
$ this-> organisation_id = auth ()-> user ()-> organisation_id;

/**
* Holen Sie sich die Kanäle, auf die die Veranstaltung übertragen werden sollte.
*
* @return \ Illuminate \ Broadcasting \ Channel | Array
*/
öffentliche Funktion Broadcaston ()

neue privatechannel zurückgeben ('Kanalname');

In dem Hörer, den Sie zuvor in EventServiceProvider definiert haben, können Sie Ihre Klasse anrufen, um die Aktualisierung der Pivot -Tabelle zu verarbeiten

Klasse MarkMessagesaSread

/**
* Erstellen Sie den Event -Hörer.
*
* @return void
*/
Öffentliche Funktion __construct ()

//

/**
* Gehen Sie mit der Veranstaltung um.
*
* @param messagesread $ event
* @return void
*/
öffentliche Funktion Handle (Messagesread $ Ereignis)

$ message_ids = $ event-> messages_ids;
$ user_id = $ event-> user_id;
$ organisation_id = $ event-> organisation_id;
(New CreateDirectMessagereadindicator (New DB))-> Execute ($ message_ids, $ user_id,
$ organisation_id);

Und schließlich kommen wir uns dem Ende näher. Wir müssen jetzt nur noch die MySQL -Abfrage betrachten

Klasse erstellte IRECTMESSAMEADIndicator

geschützt $ db;
Funktion __construct (db $ db)

$ this-> db = $ db;

/**
* Erstellen und senden Sie die Auswahlklausel für die Abfrage zurück
*
* @return String
*/
Öffentliche Funktion execute ($ message_ids = [], $ user_id, $ organisation_id)

if (count ($ message_ids) <= 0)
falsch zurückgeben;

$ created_at = date ('y-m-d h: i: s');
$ updated_at = date ('y-m-d h: i: s');
$ parameter = [];
foreach ($ message_ids als $ message_id)
array_push ($ parameters, "($ message_id, $ user_id, $ organisation_id,
'$ created_at') ");

$ parameters_string = implode (",", $ parameters);
$ query = "
In Direct_Message_Read_at einfügen (Message_ID, user_id, organisation_id,
hergestellt in)
WERTE
$ parameters_string
Auf doppelter Schlüsselaktualisierung updated_at = "$ updated_at";
";
$ this-> db :: select ($ query);

Also was ist gerade hier passiert. Grundsätzlich haben wir Message_id, User_id und organisation_id als eindeutige Kombination gekennzeichnet. Falls dieselbe User_id, die zur gleichen Organisation organisation organisation_id gehört.

Wenn Sie eine neue Zeile in eine Tabelle einfügen, wenn die Zeile ein Duplikat in eindeutiger Index oder Primärschlüssel verursacht, gibt MySQL einen Fehler aus.

Wenn Sie jedoch die Option "Auf der Anweisung" Einfügen die Option "Do Douplicate Key Update" angeben, aktualisiert MySQL stattdessen die vorhandene Zeile mit den neuen Werten.

https: // www.Mysqltutorial.org/mysql-insert-or-update-on-duplicate-key-update/
Lassen Sie mich ein paar Screenshots teilen.

Die erste Nachricht lautet:

In Direct_Message_Read_at einfügen (Message_ID, user_id, organisation_id, erstellt_at)
WERTE
(75, 3, 1, '2020-01-16 15:00:00')
Auf doppelter Schlüsseldüse aktualisiert_at = "2020-01-17 22:00:00"

Es wird diesen Eintrag in der Datenbank erstellen:

Dann kommen Sie morgen zurück und lesen dieselbe Nachricht, sie wird nur dazu führen, dass die Spalte updatated_at aktualisiert wird:

Auf diese Weise wissen Sie, wann die Nachricht zum ersten Mal gesehen wurde, und wann war das letzte Mal, als die Nachricht gelesen wurde.