Chat: Interface web


1Controlador

Vamos analisar apenas o controlador que carrega a interface web.

Os controladores Message e Event, que se comunicam com o servidor para enviar e receber mensagens, são descritos em detalhes na próxima página do tutorial.

Aqui está o código do controlador Homepage, salvo no arquivo controllers/Homepage.php:

<?php

/** Controlador raiz. */
class Homepage extends \Temma\Web\Controller {
    /** Ação raiz. */
    public function __invoke() {
        $this->_view('homepage.tpl');
    }
}
  • Linha 4: definição do controlador Homepage.
  • Linha 6: definição do método __invoke(), que corresponde à ação raiz do controlador.
  • Linha 7: o método contém apenas a instrução que define que o template a ser usado é o arquivo homepage.tpl.

2Template

Aqui está o código do template templates/homepage.tpl, que é carregado quando o usuário acessa o serviço:

<!DOCTYPE html>
<html>
<body>
    {* formulário de envio de mensagens *}
    <input id="from" type="text" placeholder="Nome" autofocus>
    <input id="text" type="text" placeholder="Mensagem">
    <button onclick="sendMessage()">Enviar</button>

    {* lista de mensagens recebidas *}
    <ul id="liste"></ul>

    {* carregamento do código javascript *}
    <script src="/chat.js"></script>
</body>
</html>
  • Linhas 5 a 7: formulário para envio de mensagens. O primeiro campo espera o nome do usuário, o segundo o texto da mensagem. Ao clicar no botão "Enviar", a função Javascript sendMessage() é executada, enviando os dados do formulário ao servidor por meio de uma requisição AJAX.
  • Linha 10: essa lista receberá um elemento adicional a cada mensagem recebida.
  • Linha 13: o arquivo que contém o código Javascript é carregado.

3Código Javascript

Aqui está o código Javascript salvo no arquivo www/chat.js:

/* *** RECEBIMENTO DE MENSAGENS VIA SSE *** */
// conexão com a fonte SSE
const evtSource = new EventSource("/event/fetch");
// escuta os eventos enviados no canal "msg"
evtSource.addEventListener("msg", function(event) {
    // criação do elemento DOM <li>
    const newElement = document.createElement("li");
    // desserialização do evento recebido
    var evtData = JSON.parse(event.data);
    // adiciona a mensagem à lista
    newElement.textContent = evtData.from + " : " + evtData.text;
    // adiciona o item à lista na página
    document.getElementById("liste").appendChild(newElement);
});

/* *** ENVIO DE MENSAGENS AO SERVIDOR *** */
// função chamada para enviar mensagens ao servidor
function sendMessage() {
    // recupera os valores do formulário
    const from = document.getElementById("from").value;
    const text = document.getElementById("text").value;
    // criação do objeto de parâmetros POST
    const formData = new FormData();
    formData.append("from", from);
    formData.append("text", text);
    // transmissão dos dados via AJAX
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/message/broadcast", true);
    xhr.send(formData);
}

A primeira parte do código abre a comunicação SSE para receber eventos do servidor. A segunda parte é a função chamada quando uma mensagem é enviada.

  • Linha 3: conexão com a fonte de eventos SSE, disponível na URL /event/fetch.
  • Linhas 5 a 14: código executado a cada evento SSE recebido no canal "msg".
    • Linha 7: criação de um nó <li>, correspondente ao elemento que conterá a mensagem e que será adicionado à lista na página web.
    • Linha 9: desserialização dos dados (recebidos no formato JSON).
    • Linha 11: no elemento <li> criado acima, escrevemos um texto formado pelo nome de quem enviou a mensagem, seguido de " : " e depois pelo texto da mensagem recebida.
    • Linha 13: o elemento <li> é adicionado à lista na página web.
  • Linhas 18 a 30: função chamada quando o usuário clica no botão "Enviar" do formulário.
    • Linhas 20 e 21: recuperação dos dados do formulário.
    • Linhas 23 a 25: criação de um objeto FormData contendo os dados do formulário.
    • Linhas 27 a 29: transmissão dos dados via AJAX para a URL /message/broadcast.