Mise à jour MySQL ou insérer plusieurs lignes - Raw Laravel SQL

Mise à jour MySQL ou insérer plusieurs lignes - Raw Laravel SQL

Problème

J'ai des messages dans le système envoyé entre plusieurs personnes comme chat de groupe. Chaque fois que quelqu'un va à charger des messages (ouvre leur boîte de réception), je dois faire blind ces messages en lecture. Je n'ai pas de modèle éloquent pour la table PIVOT DIRECT_MESSAGE_READ_AT, et j'utilise une classe qui résume la classe DB Laravel pour écrire une requête MySQL personnalisée pour ce faire.

Mon problème est, comment puis-je empêcher les entrées en double si quelqu'un ouvre le thread de message 10 fois et que le changement d'horodatage mis à jour_at à chaque fois qu'il lise le message? (Puisqu'ils ouvriront le même thread de message plusieurs fois)

Solution

Pour aider à la configuration de cette solution, montrons d'abord comment nous créons ce tableau à l'aide de Laravel Migration:

Avant le pivot, nous créons une table de messages pour stocker tous les messages des personnes. Après cela, nous créons la table pivot.

Schéma :: Create ('Direct_Message_Read_at', fonction (Blueprint $ table)
$ table-> incréments ('id');
$ table-> entier ('message_id') -> unsigned () -> nullable ();
$ Table-> Foreign ('message_id') -> références ('id') -> on ('Direct_Messages') -> ondelete ('Cascade');
$ table-> entier ('user_id') -> unsigned () -> nullable ();
$ Table-> Foreign ('user_id') -> références ('id') -> on ('utilisateurs') -> ondelete ('cascade');
$ table-> entier ('organisation_id') -> unsigned () -> nullable ();
$ Table-> Foreign ('Organisation_id') -> Références ('ID') -> On ('Organizations') -> ondelete ('Cascade');
$ Table-> TimeStamps ();
$ table-> unique (['message_id', 'user_id', 'organisation_id']); // c'est vraiment important pour
Empêcher les entrées en double par la même personne
);

Maintenant, nous voulons créer un événement et un auditeur qui traitera les messages chargés.

Imaginez que vous avez une classe responsable du chargement de tous vos messages (lorsque vous ouvrez votre boîte de réception)

Fonction publique LoadMessages ()

$ Thread_Messages = DirectMessage :: all ();
$ message_ids = $ this-> removeMyMmemessages ($ thread_messages)
événement (new messagesRead ($ messages_ids));

RemoveMymeMymeMymeMymeMymeMymeMymeMymeMymeMyMymes ($ messages)

$ message_ids = [];
// Filtrez simplement tous les messages envoyés par vous en utilisant 'WHERE (' SENDER_ID ',
auth () -> user () -> id) - Utilisez votre propre logique de code pour le faire
retourner $ message_ids;

Maintenant, à l'intérieur du messages, vous pouvez les définir et les transmettre à l'auditeur

Class MessagesRead

Utiliser la répartition, interactive avec des billets, serializesModels;
public $ messages_ids = [], $ user_id, $ organisation_id;
/ **
* Créez une nouvelle instance d'événement.
*
* @return void
* /
Fonction publique __construct ($ message_ids = [])

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

/ **
* Obtenez les chaînes sur lesquelles l'événement devrait diffuser.
*
* @return \ illuminate \ Broadcasting \ Channel | Array
* /
fonction publique Broadcaston ()

retourner new privatechannel («canal-name»);

À l'intérieur de l'auditeur que vous avez défini précédemment dans EventServiceProvider, vous pouvez appeler votre classe pour traiter la mise à jour du tableau pivot

classe MarkMessagesAsRead

/ **
* Créer l'auditeur d'événements.
*
* @return void
* /
fonction publique __construct ()

//

/ **
* Gérer l'événement.
*
* @param messagesread $ événement
* @return void
* /
Poignée de la fonction publique (Event MessageRead $)

$ message_ids = $ event-> messages_ids;
$ user_id = $ event-> user_id;
$ organisation_id = $ event-> organisation_id;
(new CreateDirectMessageReadIndicator (new db)) -> exécuter ($ message_ids, $ user_id,
$ organisation_id);

Et enfin, nous nous rapprochons de la fin. Tout ce que nous devons faire maintenant, c'est réellement regarder la requête MySQL

classe CreateDirectMessageReadIdicator

protégé $ db;
fonction __construct (db $ db)

$ this-> db = $ db;

/ **
* Construisez et renvoyez la clause SELECT pour la requête
*
* String @return
* /
Fonction publique Exécuter ($ message_ids = [], $ user_id, $ organisation_id)

if (count ($ message_ids) <= 0)
retourne false;

$ créé_at = date ('y-m-d h: i: s');
$ updated_at = date ('y-m-d h: i: s');
$ paramètres = [];
foreach ($ message_ids comme $ message_id)
array_push ($ paramètres, "($ message_id, $ user_id, $ organisation_id,
'$ créé_at') ");

$ paramètres_string = implode (",", $ paramètres);
$ query = "
Insérer dans Direct_Message_Read_At (Message_ID, User_ID, Organisation_ID,
créé à)
VALEURS
$ paramètres_string
Sur la mise à jour de la clé en double mise à jour_at = "$ updated_at";
"
$ this-> db :: select ($ query);

Alors qu'est-ce qui vient de se passer ici. Fondamentalement, nous avons marqué Message_id, user_id et organisation_id comme combinaison unique. Dans le cas où le même user_id qui appartient à la même organisation Organisation_id ouvre le même message de quelqu'un qui a ce message_id, il lancera l'erreur de duplication mysql.

Lorsque vous insérez une nouvelle ligne dans une table si la ligne provoque un double dans un index unique ou une clé primaire, MySQL émettra une erreur.

Cependant, si vous spécifiez l'option de mise à jour de clé ON en double dans l'instruction INSERT, MySQL mettra à jour la ligne existante avec les nouvelles valeurs à la place.

https: // www.mysqltutorial.org / mysql-insert-or-update-on-duplicate-key-update /
Laissez-moi partager quelques captures d'écran.

Le premier message en cours de lecture:

Insérer dans Direct_Message_Read_at (Message_ID, User_ID, Organisation_ID, Created_at)
VALEURS
(75, 3, 1, '2020-01-16 15:00:00')
Sur la mise à jour de la clé en double mise à jour_at = "2020-01-17 22:00:00"

Il produira cette entrée dans la base de données:

Ensuite, vous revenez et lisez le même message demain, cela ne fera qu'à jour la colonne Updated_at:

De cette façon, vous savez quand le message a été vu pour la première fois, et à quand remonte la dernière fois que le message a été lu.