Problema
Tenho mensagens no sistema enviado entre várias pessoas como um bate -papo em grupo. Toda vez que alguém vai para carregar mensagens (abre sua caixa de entrada), preciso que essas mensagens sinalizem como lida. Não tenho um modelo eloqüente para a tabela Direct_Message_Read_At Pivot, e estou usando uma classe que encapsula a classe DB Laravel para escrever uma consulta MySQL personalizada para fazer isso.
Meu problema é: como faço para evitar entradas duplicadas se alguém abrir o tópico da mensagem 10 vezes e fazer com que o timestamp atualizado? (Já que eles abrirão o mesmo tópico de mensagem várias vezes)
Solução
Para ajudar na configuração desta solução, vamos primeiro mostrar como criamos esta tabela usando a migração de Laravel:
Antes do pivô, criamos uma tabela de mensagens para armazenar todas as mensagens das pessoas. Depois disso, criamos a tabela de articulação.
Schema :: Create ('Direct_Message_Read_at', function (Blueprint $ tabela)
$ tabela-> incrementos ('id');
$ tabela-> integer ('message_id')-> não assinado ()-> anulável ();
$ tabela-> estrangeiro ('message_id')-> referências ('id')-> on ('diretor_messages')-> ondelete ('cascade');
$ tabela-> integer ('user_id')-> não assinado ()-> anulável ();
$ tabela-> estrangeiro ('user_id')-> referências ('id')-> on ('usuários')-> ondelete ('cascade');
$ tabela-> Inteiro ('Organização_id')-> Unsigned ()-> Nullable ();
$ tabela-> estrangeiro ('organização_id')-> referências ('id')-> on ('organizações')-> ondelete ('cascade');
$ tabela-> timestamps ();
$ tabela-> exclusivo (['message_id', 'user_id', 'organização_id']); // isso é realmente importante para
impedir entradas duplicadas pela mesma pessoa
);
Agora, queremos criar um evento e um ouvinte que processará as mensagens carregadas.
Imagine que você tem uma classe responsável por carregar todas as suas mensagens (quando você abre sua caixa de entrada)
Função pública LoadMessages ()
$ thread_messages = DirectMessage :: All ();
$ message_ids = $ this-> removeMymeSessages ($ thread_messages)
Evento (new MessageRead ($ mensagens_ids));
RemoveMymessages de função protegida ($ mensagens)
$ message_ids = [];
// Simplesmente filtra todas as mensagens enviadas por você usando 'Where (' Sender_id ',
auth ()-> user ()-> id)-use sua própria lógica de código para fazer isso
retornar $ message_ids;
Agora, dentro da leitura das mensagens, você pode defini -las e passá -las para o ouvinte
Mensagens de classe
use despacho, interraeswithsockets, serializa models;
public $ mensagens_ids = [], $ user_id, $ organização_id;
/**
* Crie uma nova instância de evento.
*
* @return void
*/
função pública __construct ($ message_ids = [])
$ this-> message_ids = $ message_ids;
$ this-> user_id = auth ()-> user ()-> id;
$ this-> organização_id = auth ()-> user ()-> organização_id;
/**
* Obtenha os canais que o evento deve transmitir.
*
* @return \ iluminate \ broadcasting \ canal | Array
*/
Função pública Broadcaston ()
devolver o novo privatechannel ('canal-name');
Dentro do ouvinte que você definiu anteriormente no EventServiceProvider, você pode ligar para sua classe para processar a atualização da tabela Pivot
Classe MarkMessagesAsRead
/**
* Crie o ouvinte do evento.
*
* @return void
*/
Função pública __construct ()
//
/**
* Lidar com o evento.
*
* @Param MessageRead $ Evento
* @return void
*/
Handle de função pública (Evento MessageRead $)
$ message_ids = $ event-> messages_ids;
$ user_id = $ event-> user_id;
$ organização_id = $ event-> organização_id;
(novo CreateRectMessageReadIndicator (novo db))-> Execute ($ message_ids, $ user_id,
$ organização_id);
E finalmente, estamos chegando mais perto do fim. Tudo o que precisamos fazer agora é realmente olhar para a consulta MySQL
CLASSE CREATEDIRECTMESSAGEREADIDICATOR
$ db protegido;
função __construct (db $ db)
$ this-> dB = $ dB;
/**
* Construa e retorne a cláusula selecionada para a consulta
*
* @return string
*/
função pública Execute ($ message_ids = [], $ user_id, $ organização_id)
if (count ($ message_ids) <= 0)
retorna falso;
$ criate_at = date ('y-m-d h: i: s');
$ update_at = date ('y-m-d h: i: s');
$ parâmetros = [];
foreach ($ message_ids como $ message_id)
Array_push ($ parâmetros, "($ message_id, $ user_id, $ organização_id,
'$ creted_at') ");
$ parameters_string = implode (",", $ parâmetros);
$ query = "
Inserir em diretor_message_read_at (message_id, user_id, organização_id,
criado em)
Valores
$ parâmetros_string
Na Key Duplicate Key Update Update_at = "$ UPDATED_AT";
";
$ this-> db :: select ($ query);
Então, o que acabou de acontecer aqui. Basicamente, marcamos message_id, user_id e organização_id como a combinação única. Caso o mesmo user_id que pertence à mesma organização organização_id abre a mesma mensagem de alguém que tem esse Message_id, ele lançará o erro de duplicação do MySQL.
Quando você insere uma nova linha em uma tabela se a linha causar uma duplicata em índice exclusivo ou chave primária, o MySQL emitirá um erro.
No entanto, se você especificar a opção de atualização de chaves on duplicados na instrução Insert, o MySQL atualizará a linha existente com os novos valores em vez disso.
https: // www.mysqltutorial.org/mysql-insert-or-update-on-duplicate-key-update/
Deixe -me compartilhar algumas capturas de tela.
A primeira mensagem sendo lida:
Inserir em diretor_message_read_at (message_id, user_id, organização_id, criado_at)
Valores
(75, 3, 1, '2020-01-16 15:00:00')
Na Key Duplicate Key Update Atualizada_at = "2020-01-17 22:00:00"
Ele produzirá esta entrada no banco de dados:
Então você volta e lê a mesma mensagem amanhã, ela fará com que apenas a coluna atualizada_at seja atualizada:
Dessa forma, você sabe quando a mensagem foi vista pela primeira vez e quando foi a última vez que a mensagem foi lida.