Cuando los comentarios normales ya no son suficientes, llega el momento de crear un chat.

Con un chat, los usuarios pueden comunicarse entre sí, aumentando el interés en el sitio web. Es un elemento importante para plataformas de webinars, portales con servicio de atención al cliente y páginas donde se necesita una comunicación más dinámica, que no sea un foro. Esta guía te ayudará a combinar conocimientos de HTML, JS, PHP y AJAX para crear un producto terminado.

¿Cómo debe ser el chat?

La comodidad del usuario es lo más importante. Asegúrate de que el chat cumpla con los requisitos modernos:

  • Los mensajes se muestran correctamente en todos los dispositivos.
  • La carga y el envío de mensajes se realizan sin actualizar la página.
  • Hay contenido adicional: imágenes, mensajes de audio, emojis, stickers, etc.

Estructura del chat en HTML

Primero, creamos el formulario de envío y el contenedor para mostrar los mensajes (aquí un ejemplo):

<div class='chat'>
    <div class='chat-messages'>
        <div class='chat-messages__content' id='messages'>
            Cargando...
        </div>
    </div>
    <div class='chat-input'>
        <form method='post' id='chat-form'>
            <input type='text' id='message-text' class='chat-form__input' placeholder='Ingrese mensaje'> <input type='submit' class='chat-form__submit' value='=>'>
        </form>
    </div>
</div>

Definimos los estilos

.chat {
    border:1px solid #333;
    margin:15px;
    width:40%;
    height:70%;
    background:#555;
    color:#fff;
}

.chat-messages {
    min-height:93%;
    max-height:93%;
    overflow:auto;
}

.chat-messages__content {
    padding:1px;
}

.chat__message {
    border-left:3px solid #333;
    margin-top:2px;
    padding:2px;
}

.chat__message_black {
    border-color:#000;
}

.chat__message_blue {
    border-color:blue;
}

.chat__message_green {
    border-color:green;
}

.chat__message_red {
    border-color:red;
}

.chat-input {
    min-height:6%;
}

input {
    font-family:arial;
    font-size:16px;
    vertical-align:middle;
    background:#333;
    color:#fff;
    border:0;
    display:inline-block;
    margin:1px;
    height:30px;
}

.chat-form__input {
    width:79%;
}

.chat-form__submit {
    width:18%;
}
Captura de pantalla que muestra un sencillo chat con mensajes intercambiados entre un usuario ("user") y un administrador ("admin"). Se incluye un campo de entrada de texto para enviar nuevos mensajes.
Este es un ejemplo básico de cómo se podría estructurar un chat simple. ¡Aprende a crear tu propio sistema de chat!

Primero, nos enfocamos en las funciones principales del chat y luego mejoramos la apariencia.

Parte principal del chat en JS + PHP

Los mensajes se enviarán y cargarán usando AJAX. En JavaScript, escribimos las funciones para trabajar con la interfaz y la conexión con la parte del servidor, y en PHP, los métodos para procesar los datos recibidos e interactuar con la base de datos.

Creamos variables en JS

var messages__container = document.getElementById('messages'); 
//Contenedor de mensajes - el script añadirá mensajes aquí

var interval = null; //Variable con el intervalo de carga de mensajes

var sendForm = document.getElementById('chat-form'); //Formulario de envío
var messageInput = document.getElementById('message-text'); //Input para el texto del mensaje

Creamos una función para las peticiones

Recibe la variable act, que contiene uno de tres valores: auth (autorización), load (carga) y send (envío). Dependiendo del valor, se enviará información diferente al archivo PHP.

function send_request(act, login = null, password = null) {
    var var1 = null;
    var var2 = null;

    if(act == 'auth') {
        var1 = login;
        var2 = password;
    } else if(act == 'send') {
        var1 = messageInput.value;
    }

    $.post('includes/chat.php',{ 
        act: act,
        var1: var1,
        var2: var2
    }).done(function (data) { 
        messages__container.innerHTML = data;
        if(act == 'send') {
            messageInput.value = '';
        }
    });
}

Creamos una función para actualizar el chat

Y establecemos un intervalo para su ejecución:

function update() {
    send_request('load');
}
interval = setInterval(update,500);

sendForm.onsubmit = function () {
    send_request('send');
    return false; 
};

Ahora, nos ocupamos del manejador. Primero, con la función session_start() se inicia la sesión, luego se conecta a la base de datos:

session_start();
$db = mysqli_connect("localhost","login","password"); 
mysqli_select_db($db,"chat");
$_SESSION['login'] = 'admin';
$_SESSION['password'] = 'admin';
$_SESSION['id'] = 1;

Creamos una función de autorización

function auth($db,$login,$pass) {
    $result = mysqli_query($db,"SELECT * FROM userlist WHERE login='$login' AND password='$pass'");
    if($result) {
        if(mysqli_num_rows($result) == 1) {
            $user = mysqli_fetch_array($result); 
            $_SESSION['login'] = $login;
            $_SESSION['password'] = $pass;
            $_SESSION['id'] = $user['id'];
            return true; 
        } else {
            unset($_SESSION); 
            return false;
        }
    } else {
        return false; 
    }
}

Creamos una función de carga

function load($db) {
    $echo = "";
    if(auth($db,$_SESSION['login'],$_SESSION['password'])) {
        $result = mysqli_query($db,"SELECT * FROM messages"); 
        if($result) {
            if(mysqli_num_rows($result) >= 1) {
                while($array = mysqli_fetch_array($result)) {
                    $user_result = mysqli_query($db,"SELECT * FROM userlist WHERE id='$array[user_id]'");
                    if(mysqli_num_rows($user_result) == 1) {
                        $user = mysqli_fetch_array($user_result);
                        $echo .= "<div class='chat__message chat__message_$user[nick_color]'><b>$user[login]:</b> $array[message]</div>"; 
                    }
                }
            } else {
                $echo = "No hay mensajes!";
            }
        }
    } else {
        $echo = "Problema de autorización";
    }
    return $echo;
}

Creamos una función para enviar mensajes

function send($db,$message) {
    if(auth($db,$_SESSION['login'],$_SESSION['password'])) {
        $message = htmlspecialchars($message);
        $message = trim($message); 
        $message = addslashes($message); 
        $result = mysqli_query($db,"INSERT INTO messages (user_id,message) VALUES ('$_SESSION[id]','$message')");
    }
    return load($db); 
}

La función ya incluye una validación simple, pero se pueden agregar otras medidas de protección contra inyecciones y spam:

  • Verificación de mensajes duplicados.
  • Eliminación de enlaces externos.
  • Censura de malas palabras.
  • Pre-moderación de mensajes para algunos grupos de usuarios, etc.

Ahora, cuando todas las funciones están listas, escribimos su llamada.

Llamamos a las funciones

if(isset($_POST['act'])) {$act = $_POST['act'];}
if(isset($_POST['var1'])) {$var1 = $_POST['var1'];}
if(isset($_POST['var2'])) {$var2 = $_POST['var2'];}

switch($_POST['act']) {
    case 'load': 
        $echo = load($db); 
    break;

    case 'send': 
        if(isset($var1)) {
            $echo = send($db,$var1); 
        }
    break;

    case 'auth': 
        if(isset($var1) && isset($var2)) {
            if(auth($db,$var1,$var2)) {
                $echo = load($db);
            }
        }
    break;
}

echo $echo;

En el frontend aún no hemos implementado la autenticación, pero ya podemos probar el chat, porque al principio los datos del administrador se almacenaron en la sesión.

Captura de pantalla de una interfaz de chat simple en la que se muestra el mensaje "Cargando..." en la sección principal y un campo de entrada de texto con el mensaje "hola" escrito.
Ejemplo de interfaz de usuario de un chat mostrando el mensaje de carga mientras se establece la conexión.

Ahora que el chat funciona, es hora de agregar la autenticación. Para ello, se puede crear un formulario separado en el frontend, o usar ventanas modales. En la función send_request(), añadimos el envío de la solicitud:

$.post('includes/chat.php',{
    act: act,
    var1: var1,
    var2: var2
}).done(function (data) {
    messages__container.innerHTML = data;
    if(data == 'Problema de autorización') {
        clearInterval(interval); 
        if(login == null && password == null) {
            login = prompt('Ingrese su usuario: ');
            if(login != null) {
                password = prompt('Ingrese su contraseña: ');
                send_request('auth',login,password); 
            }
        }
    } 
    if(act == 'auth') {
        interval = setInterval(update,500); 
    }
    if(act == 'send') {
        messageInput.value = '';
    }
});

Funciones adicionales

Tenemos las funciones mínimas del chat y el producto se puede lanzar, pero añadiremos algunas cosas más útiles.

Emojis

Creamos nuestro propio conjunto de emojis para el chat. Funcionará así:

  • El usuario abre una ventana especial y hace clic en un emoji.
  • Se añade el código del emoji al campo de entrada (por ejemplo, :sad: o :crazy:).
  • Al mostrar el mensaje, el código del emoji se reemplaza por una imagen.

Primero, añadimos un contenedor con emojis y un botón para abrirlo:

<form method='post' id='chat-form'>
<div class='emojis-container emojis-container_hidden' id='emojis'></div>
    <img src='/images/emojis/happy.png' class='emoji-img' id='emoji-button'>
<input type='text' id='message-text' class='chat-form__input' placeholder='Ingrese mensaje'> 
<input type='submit' class='chat-form__submit' value='=>'>
</form>

Definimos los estilos:

.emojis-container {
    position:absolute;
    z-index:100;
    background:#555;
    border:1px solid #333;
    padding:2px;
    max-width:38%;
    top:20px;
}

.emojis-container_hidden {
    left:-9999999999999999px;
}

.emoji-img {
    vertical-align:middle;
    width:20px;
    margin:1px;
    cursor:pointer;
}

Añadimos el script para cargar los emojis y abrir el menú:

var emojis__container = document.getElementById('emojis');
var emojis__button = document.getElementById('emoji-button');
var showed = false;

function getEmojis() {
    $.post('/includes/chat.php',{act: 'load-emojis'}).done(function (data) {
        emojis__container.innerHTML = data;
    });
}

function showEmojis() {
    if(showed) {
        emojis__container.setAttribute('class','emojis-container emojis-container_hidden');
        showed = false;
    } else {
        emojis__container.setAttribute('class','emojis-container');
        showed = true;
    }
}

Y ahora la función para añadir emojis al campo:

function addEmoji(title) {
    messageInput.value += " " + title + " ";
    messageInput.focus();
}

Después, especifiquemos cuándo se llaman las funciones:

$(document).ready(function (){
    $(".emoji-add").on("click", function () {addEmoji($(this).attr('title'));});
});
emojis__button.addEventListener('click',showEmojis); 

getEmojis(); 

Ahora, procedemos a cargar los emojis y a su transformación en PHP:

function getEmojis() {
    $dir = '../images/emojis';
    $echo = "";
    $files = scandir($dir);

    for($i = 0; $i != count($files); $i++) {
        $ext = explode('.',$files[$i]);
        if($ext[1] == 'png') {
            $echo .= "<img src='/images/emojis/".$files[$i]."' title=':".$ext[0].":' class='emoji-img emoji-add'> ";
        } 
    }
    return $echo;
}

Esta función escanea la carpeta de emojis y luego comprueba la extensión de los archivos. Es muy cómoda porque muestra en formato PNG todos los emojis que hemos añadido.

Para llamarla, añadimos otro case a la función switch() al final del controlador:

case 'load-emojis': 
    $echo = getEmojis();
break;

Ahora, usando expresiones regulares, podemos reemplazar el código del emoji por la imagen:

function transformEmoji($message) {
    $pattern = '/(\:\S*\:)/i'; 
    if(preg_match($pattern,$message,$matches)) {
        $path = explode(":",$matches[0]);
        if(file_exists("../images/emojis/".$path[1].".png")) {
            $message = preg_replace("/".$matches[0]."/","<img src='/images/emojis/$path[1].png' class='emoji-img'>",$message);
        }
        $message = transformEmoji($message); 
    }
    return $message;
}

Esta función se llama al cargar los mensajes:

$array['message'] = transformEmoji($array['message']);

Responder a mensajes

Para añadir la posibilidad de responder a alguien en concreto, modificamos la función addEmoji(). Al hacer clic en el nombre de usuario del interlocutor, cambiará el texto del campo de entrada.

Para ello, en load(), cambiamos el formato de los mensajes, añadiendo <span> al nombre de usuario:

$echo .= "<div class='chat__message chat__message_$user[nick_color]'><b><span class='answer-span'>$user[login]</span>:</b> $array[message]</div>";

Escribimos la función:

function addAnswer(login) {
    messageInput.value = login + ", " + messageInput.value;
    messageInput.focus();
}

Y llamamos a la función:

$(document).ready(function (){
    $(".add-answer").on("click", function () {addAnswer($(this).text());});
});

Conclusión

Un solo artículo no es suficiente para cubrir todas las posibilidades de PHP y JS para el desarrollo de chats. Con estos lenguajes es fácil añadir:

  • Respuestas a mensajes concretos.
  • Formato de texto.
  • Envío de audio.
  • Diferentes “salas”.
  • Un chatbot y mucho más.

Categorizado en:

Programación,