Aktualizacja MySQL lub wstaw wiele wierszy - Raw Laravel SQL

Aktualizacja MySQL lub wstaw wiele wierszy - Raw Laravel SQL

Problem

Mam wiadomości w systemie wysyłane między wieloma osobami jako czat grupowy. Za każdym razem, gdy ktoś idzie do ładowania wiadomości (otwiera swoją skrzynkę odbiorczą), muszę uzyskać te wiadomości jako odczytanie. Nie mam elokwentnego modelu dla tabeli obrotowej Direct_Message_Read_at i używam klasy, która obejmuje klasę Laravel DB do napisania niestandardowego zapytania MySQL, aby to zrobić.

Mój problem polega na tym, w jaki sposób zapobiegać zduplikowaniu wpisów, jeśli ktoś otworzy wątek wiadomości 10 razy, i zmienić aktualizację znacznika czasu_at? (Ponieważ wielokrotnie otwierają ten sam wątek wiadomości)

Rozwiązanie

Aby pomóc w konfiguracji tego rozwiązania, najpierw pokażmy, jak tworzymy tę tabelę za pomocą migracji Laravel:

Przed obrotem utworzylibyśmy tabelę wiadomości do przechowywania wszystkich wiadomości od ludzi. Następnie tworzymy tabelę obrotu.

Schema :: „Direct_message_read_at”, funkcja (Blueprint $ tabela)
$ table-> przyrosty („id”);
$ TABLE-> INTEGER ('MEASSE_ID')-> unsigned ()-> nullable ();
$ TABLE-> obcokrajowe ('message_id')-> referencje ('id')-> on ('Direct_Messages')-> onDelete ('cascade');
$ TABLE-> Integer ('user_id')-> unsigned ()-> nullable ();
$ TABLE-> obcokrajowe ('user_id')-> referencje ('id')-> on ('Users')-> onDelete ('cascade');
$ TABLE-> INTEGER ('Organizacja_id')-> unsigned ()-> nullable ();
$ TABLE-> zagraniczne ('organizacja_id')-> References ('id')-> on ('Organizations')-> onDelete ('cascade');
$ TABLE-> Timestamps ();
$ tabela-> unikalne (['message_id', 'user_id', 'organizacja_id']); // to jest naprawdę ważne dla
Zapobiegaj zduplikowanym wpisom tej samej osoby
);

Teraz chcemy utworzyć zdarzenie i słuchacz, który będzie przetwarzał załadowane wiadomości.

Wyobraź sobie, że masz klasę odpowiedzialną za ładowanie wszystkich wiadomości (po otwarciu skrzynki odbiorczej)

Funkcja publiczna loadmessages ()

$ Thread_Messages = DirectMessage :: all ();
$ message_ids = $ this-> resureMyMessages ($ thread_messages)
event (nowy komunikat Read ($ message_ids));

Protected Function RemousemMessages ($ Messages)

$ message_ids = [];
// po prostu odfiltruj wszystkie wiadomości wysyłane przez Ciebie za pomocą „gdzie („ Sender_id ”,
Auth ()-> user ()-> id)-Użyj własnej logiki kodu, aby to zrobić
return $ message_ids;

Teraz w wiadomościach, czy możesz je zdefiniować i przekazać słuchaczowi

Messelass Class Read

Używaj wysyłki, interaktswithsockets, serializeModels;
public $ message_ids = [], $ user_id, $ organizacja_id;
/**
* Utwórz nową instancję wydarzenia.
*
* @return void
*/
funkcja publiczna __Construct ($ message_ids = [])

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

/**
* Zdobądź kanały, na których wydarzenie powinno nadać.
*
* @return \ Illuminate \ Broadcasting \ kanał | tablica
*/
Funkcja publiczna Broadcast ()

zwrócić nowy prywatechannel („kanał-nazwa”);

Wewnątrz słuchacza, który wcześniej zdefiniowałeś w EventerviceProvider

klasa markmessagesSread

/**
* Utwórz słuchacz wydarzeń.
*
* @return void
*/
funkcja publiczna __Construct ()

//

/**
* Obsługuj wydarzenie.
*
* @Param MomessionSereD $ wydarzenie
* @return void
*/
Publiczny uchwyt funkcji (MessageRead $ Event)

$ message_ids = $ event-> message_ids;
$ user_id = $ event-> user_id;
$ organizacja_id = $ event-> organizacja_id;
(nowy CreatedirectMessageReadIndicator (nowy db))-> Wykonaj ($ message_ids, $ user_id,
$ organizacja_id);

I wreszcie zbliżamy się do końca. Teraz musimy teraz spojrzeć na zapytanie MySQL

klasa CreatirectMessageReadIndIndicator

chronione $ db;
Funkcja __Construct (db $ db)

$ this-> db = $ db;

/**
* Zbuduj i zwróć klauzulę Wybierz zapytanie
*
* Ciąg @return
*/
Funkcja publiczna Wykonaj ($ message_ids = [], $ user_id, $ organizacja_id)

if (count ($ message_ids) <= 0)
zwrócić fałsz;

$ Created_at = data ('y-m-d h: i: s');
$ aktualizate_at = data ('y-m-d h: i: s');
$ parameters = [];
foreach ($ message_ids as $ message_id)
array_push ($ parameters, "($ message_id, $ user_id, $ organizacja_id,
„$ Created_AT”) ”);

$ parameters_string = implode (",", $ parameters);
$ query = "
Wstaw do Direct_Message_Read_at (Message_id, User_id, Organization_ID,
utworzony_at)
Wartości
$ parameters_string
Na zduplikowaniu aktualizacji kluczowej aktualizacji_at = "$ aktualizate_at";
";
$ this-> db :: select ($ query);

Więc co się tutaj wydarzyło. Zasadniczo oznaczyliśmy Message_id, User_id i Organization_ID jako unikalna kombinacja. W przypadku, gdy ten sam użytkownik, który należy do tej samej organizacji organizacji Organizacja Organizacja Otwiera tę samą wiadomość od kogoś, kto ma ten komunikat_id, rzuci błąd duplikacji MySQL.

Po wstawieniu nowego wiersza do tabeli, jeśli wiersz powoduje duplikat w unikalnym indeksie lub kluczu podstawowym, MySQL wystawi błąd.

Jeśli jednak określisz opcję ON Duplicate Key Update w instrukcji Wstaw, MySQL zaktualizuje istniejący wiersz z nowymi wartościami.

https: // www.MysqlTutorial.org/mysql-insert-albo-update-on-on-duplicate-key-update/
Pozwól mi podzielić się z kilkoma zrzutem ekranu.

Pierwsza wiadomość jest czytana:

Wstaw do DIRECT_MESSAGE_READ_AT (Message_id, User_id, Organization_ID, Created_at)
Wartości
(75, 3, 1, „2020-01-16 15:00:00”)
Na duplikat aktualizacji kluczowej aktualizacji_at = "2020-01-17 22:00:00"

Wytworzy ten wpis w bazie danych:

Potem wrócisz i czytasz tę samą wiadomość jutro, spowoduje to zaktualizowanie tylko zaktualizowanej kolumny:

W ten sposób wiesz, kiedy wiadomość była widziana po raz pierwszy, a kiedy ostatnio przeczytano wiadomość.