[Javascript-MySQL] Modificar estado de usuario

Actualizar el estado del perfil con jQuery, AJAX y base de datos sin recargar la página

En muchas aplicaciones web con perfiles de usuario existe una funcionalidad muy sencilla pero muy útil: permitir que cada usuario pueda indicar qué está haciendo, qué piensa o simplemente escribir un pequeño mensaje asociado a su perfil.

En este artículo vamos a ver cómo implementar este comportamiento utilizando jQuery, AJAX y una base de datos, de forma que el usuario pueda modificar su estado y visualizar inmediatamente el resultado sin necesidad de recargar la página.

La idea es sencilla:

  • El usuario introduce un nuevo estado.
  • jQuery captura la acción.
  • Se realiza una petición AJAX al servidor.
  • El servidor procesa y guarda la información en la base de datos.
  • La respuesta vuelve al navegador.
  • La interfaz se actualiza dinámicamente.

Todo esto ocurre sin abandonar la página y sin realizar una recarga completa del documento.

El funcionamiento de la aplicación

Por defecto, cuando el usuario todavía no ha establecido ningún estado, podemos mostrar un mensaje genérico:

¿Qué piensas?

Este texto funciona como un estado inicial y también como una invitación al usuario para introducir su propio mensaje.

Cuando el usuario modifica el estado, la aplicación se encarga de guardar el nuevo contenido y actualizar la interfaz inmediatamente.

El flujo general sería el siguiente:

┌───────────────────────┐
│       USUARIO         │
│ Escribe nuevo estado  │
└───────────┬───────────┘
            │
            ▼
┌───────────────────────┐
│        jQuery         │
│ Captura el evento     │
└───────────┬───────────┘
            │
            │ AJAX
            ▼
┌───────────────────────┐
│       SERVIDOR        │
│ PHP / backend         │
└───────────┬───────────┘
            │
            ▼
┌───────────────────────┐
│      BASE DE DATOS    │
│ Guarda nuevo estado   │
└───────────┬───────────┘
            │
            ▼
┌───────────────────────┐
│      RESPUESTA AJAX   │
└───────────┬───────────┘
            │
            ▼
┌───────────────────────┐
│       jQuery          │
│ Actualiza el DOM      │
└───────────────────────┘

La principal ventaja de este modelo es que el navegador no necesita volver a descargar y renderizar toda la página después de cada modificación.

¿Qué significa actualizar datos sin recargar?

En una aplicación web tradicional, podríamos enviar un formulario de esta manera:

<form action="actualizar_estado.php" method="POST">

    <input
        type="text"
        name="estado"
        placeholder="¿Qué piensas?"
    >

    <button type="submit">
        Guardar
    </button>

</form>

Al enviar el formulario, el navegador realiza una petición al servidor y normalmente recibe una nueva página HTML.

El resultado sería algo parecido a:

Navegador
    ↓
POST
    ↓
Servidor
    ↓
Base de datos
    ↓
Nueva respuesta HTML
    ↓
Recarga de página

Con AJAX podemos modificar este comportamiento.

La petición sigue llegando al servidor y la base de datos sigue almacenando la información, pero la petición se realiza en segundo plano.

Navegador
    ↓
jQuery AJAX
    ↓
Servidor
    ↓
Base de datos
    ↓
Respuesta
    ↓
Actualizar DOM
    ↓
SIN RECARGAR

¿Qué papel desempeña jQuery?

jQuery facilita considerablemente la interacción con el DOM y la realización de peticiones AJAX.

En este caso podemos utilizarlo para:

  • Detectar cuándo el usuario modifica el estado.
  • Obtener el contenido del campo de texto.
  • Enviar los datos al servidor.
  • Procesar la respuesta.
  • Actualizar el contenido mostrado en pantalla.
  • Mostrar mensajes de éxito o error.

Por ejemplo:

$("#guardar-estado").on("click", function () {

    const estado = $("#estado").val();

    $.ajax({
        url: "actualizar_estado.php",
        type: "POST",
        data: {
            estado: estado
        },
        success: function (respuesta) {

            console.log("Estado actualizado");

        }
    });

});

El código anterior no recarga la página. La petición se realiza mediante AJAX y el servidor responde de forma independiente.

La interfaz del estado

Podemos crear una interfaz sencilla utilizando HTML:

<div id="perfil">

    <div id="estado-actual">
        ¿Qué piensas?
    </div>

    <input
        type="text"
        id="estado"
        placeholder="Escribe un nuevo estado..."
    >

    <button id="guardar-estado">
        Guardar
    </button>

</div>

La aplicación dispone de tres elementos principales:

  • #estado-actual: muestra el estado actualmente almacenado.
  • #estado: permite introducir el nuevo estado.
  • #guardar-estado: inicia el proceso de actualización.

Enviar el estado mediante AJAX

Ahora podemos conectar el formulario con nuestro backend.

$("#guardar-estado").on("click", function () {

    const estado = $("#estado").val().trim();

    if (!estado) {
        return;
    }

    $.ajax({

        url: "actualizar_estado.php",

        type: "POST",

        data: {
            estado: estado
        },

        success: function (respuesta) {

            $("#estado-actual").text(estado);

            $("#estado").val("");

        },

        error: function () {

            alert("No se ha podido actualizar el estado.");

        }

    });

});

Una vez realizada correctamente la petición, modificamos directamente el contenido del elemento:

$("#estado-actual").text(estado);

Por eso el usuario ve inmediatamente el nuevo estado sin que el navegador tenga que recargar la página.

¿Qué ocurre en el servidor?

El navegador no debería modificar directamente la base de datos.

El cliente envía los datos al servidor y es el backend el responsable de validar y almacenar la información.

Un ejemplo simplificado utilizando PHP sería:

<?php

$estado = $_POST['estado'] ?? '';

$estado = trim($estado);

if ($estado === '') {
    exit;
}

// Aquí realizaríamos la actualización
// de la base de datos.

echo "ok";

En una aplicación real deberíamos añadir validación, autenticación, autorización y consultas preparadas antes de modificar cualquier dato.

Guardar el estado en MySQL

Supongamos que tenemos una tabla de usuarios como la siguiente:

CREATE TABLE usuarios (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nombre VARCHAR(100) NOT NULL,
    email VARCHAR(150) NOT NULL,
    estado VARCHAR(255) DEFAULT NULL
);

El campo:

estado VARCHAR(255) DEFAULT NULL

será el encargado de almacenar el estado del usuario.

Cuando el usuario modifique su perfil, el servidor puede ejecutar una consulta como:

UPDATE usuarios
SET estado = ?
WHERE id = ?;

Los valores deben enviarse mediante parámetros utilizando una consulta preparada.

Ejemplo con PHP y PDO

Una implementación algo más apropiada sería:

<?php

$pdo = new PDO(
    "mysql:host=localhost;dbname=mi_base_de_datos;charset=utf8mb4",
    "usuario",
    "contraseña",
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    ]
);

$estado = trim($_POST['estado'] ?? '');
$usuarioId = 1;

if ($estado === '') {
    http_response_code(400);
    echo "Estado vacío";
    exit;
}

if (mb_strlen($estado) > 255) {
    http_response_code(400);
    echo "El estado es demasiado largo";
    exit;
}

$stmt = $pdo->prepare(
    "UPDATE usuarios
     SET estado = :estado
     WHERE id = :id"
);

$stmt->execute([
    ':estado' => $estado,
    ':id' => $usuarioId
]);

echo "ok";

La consulta preparada es importante porque evita construir consultas SQL concatenando directamente datos proporcionados por el usuario.

Pero hay un detalle fundamental: ¿quién es el usuario?

En el ejemplo anterior hemos utilizado:

$usuarioId = 1;

Esto solamente sirve para simplificar el ejemplo.

En una aplicación real jamás deberíamos confiar en un ID enviado libremente desde JavaScript para decidir qué usuario modificar.

El servidor debería obtener la identidad del usuario a partir de la sesión autenticada.

Por ejemplo:

$usuarioId = $_SESSION['usuario_id'];

De esta manera el servidor determina quién está realizando la operación y solamente permite modificar su propio perfil.

Devolver una respuesta estructurada

En lugar de devolver simplemente:

ok

es mucho más práctico devolver una respuesta JSON.

<?php

header('Content-Type: application/json; charset=utf-8');

echo json_encode([
    'success' => true,
    'message' => 'Estado actualizado correctamente',
    'estado' => $estado
]);

Así JavaScript puede interpretar fácilmente el resultado.

$.ajax({

    url: "actualizar_estado.php",

    type: "POST",

    dataType: "json",

    data: {
        estado: estado
    },

    success: function (respuesta) {

        if (respuesta.success) {

            $("#estado-actual")
                .text(respuesta.estado);

            $("#estado").val("");

        }

    },

    error: function () {

        alert("No se ha podido actualizar el estado.");

    }

});

El flujo completo

En este punto podemos entender perfectamente qué ocurre internamente.

1. El usuario escribe un estado
              ↓
2. Pulsa "Guardar"
              ↓
3. jQuery obtiene el contenido
              ↓
4. jQuery realiza una petición AJAX
              ↓
5. PHP recibe los datos
              ↓
6. PHP valida la información
              ↓
7. PHP identifica al usuario mediante sesión
              ↓
8. PHP ejecuta UPDATE en MySQL
              ↓
9. MySQL almacena el nuevo estado
              ↓
10. PHP devuelve JSON
              ↓
11. jQuery recibe la respuesta
              ↓
12. jQuery modifica el DOM
              ↓
13. El nuevo estado aparece inmediatamente

¿Por qué no se recarga la página?

La clave está en que la petición AJAX es independiente de la navegación principal del documento.

El navegador mantiene la página actual en memoria mientras realiza la petición al servidor.

Cuando llega la respuesta, JavaScript puede modificar solamente la parte necesaria de la interfaz.

Por ejemplo:

$("#estado-actual").text(respuesta.estado);

No necesitamos volver a descargar:

  • El HTML completo.
  • Las hojas de estilo.
  • Los scripts.
  • Las imágenes.
  • El resto del perfil.

Solamente modificamos el elemento que contiene el estado.

Ventajas de este enfoque

Mejor experiencia de usuario

El usuario puede modificar su información sin abandonar la página actual.

Menos tráfico innecesario

No es necesario solicitar de nuevo todo el documento HTML cada vez que cambia un pequeño dato.

Interfaz más dinámica

La aplicación puede reaccionar inmediatamente ante las acciones del usuario.

Separación entre frontend y backend

El navegador se ocupa de la interfaz y la interacción, mientras que el servidor se encarga de la validación y persistencia de los datos.

Validación del estado

Nunca deberíamos almacenar directamente cualquier contenido recibido desde el navegador.

El servidor debería comprobar, como mínimo:

  • Que el usuario está autenticado.
  • Que tiene permisos para modificar su perfil.
  • Que el estado no está vacío.
  • Que no supera la longitud máxima permitida.
  • Que el contenido cumple las reglas de la aplicación.

Por ejemplo:

$estado = trim($_POST['estado'] ?? '');

if ($estado === '') {
    http_response_code(400);
    exit;
}

if (mb_strlen($estado) > 255) {
    http_response_code(400);
    exit;
}

La validación del servidor es obligatoria aunque también hagamos validación en JavaScript.

La validación JavaScript mejora la experiencia de usuario, pero no constituye una barrera de seguridad, ya que el cliente puede manipularse.

Evitar problemas de XSS

Cuando mostramos información introducida por un usuario debemos tener especial cuidado con el contenido que insertamos en el DOM.

Para mostrar texto plano con jQuery es preferible utilizar:

$("#estado-actual").text(respuesta.estado);

en lugar de:

$("#estado-actual").html(respuesta.estado);

.text() trata el contenido como texto, mientras que .html() interpreta el contenido como HTML.

Si un usuario introduce algo como:

<script>alert("Hola")</script>

no queremos que ese contenido termine siendo interpretado como código ejecutable.

La salida debe estar correctamente tratada y, cuando corresponda, también debe existir una política de seguridad de contenido adecuada.

Protección contra CSRF

En una aplicación con usuarios autenticados también debemos considerar los ataques CSRF (Cross-Site Request Forgery).

Una petición que modifica información no debería depender únicamente de que exista una sesión válida.

Una solución habitual consiste en utilizar un token CSRF que el servidor genera y que debe acompañar a la petición.

Conceptualmente:

Usuario autenticado
        ↓
Token CSRF
        ↓
Petición AJAX
        ↓
Servidor valida token
        ↓
Actualiza base de datos

Esto añade una capa adicional de protección a las operaciones que modifican datos.

Mostrar estados de carga y errores

Una interfaz profesional no debería quedarse aparentemente congelada mientras espera la respuesta del servidor.

Podemos desactivar temporalmente el botón:

$("#guardar-estado")
    .prop("disabled", true)
    .text("Guardando...");

Y volver a activarlo cuando termine la operación:

$("#guardar-estado")
    .prop("disabled", false)
    .text("Guardar");

También podemos mostrar mensajes como:

Guardando...
Estado actualizado correctamente
No se ha podido actualizar el estado
La sesión ha expirado

Esto proporciona al usuario información clara sobre lo que está ocurriendo.

Una implementación completa del frontend

Uniendo los conceptos anteriores podemos construir un ejemplo más completo:

$("#guardar-estado").on("click", function () {

    const boton = $(this);
    const estado = $("#estado").val().trim();

    if (!estado) {
        $("#mensaje")
            .text("Escribe un estado antes de guardar.");

        return;
    }

    boton
        .prop("disabled", true)
        .text("Guardando...");

    $("#mensaje").text("");

    $.ajax({

        url: "actualizar_estado.php",

        type: "POST",

        dataType: "json",

        data: {
            estado: estado
        },

        success: function (respuesta) {

            if (respuesta.success) {

                $("#estado-actual")
                    .text(respuesta.estado);

                $("#estado")
                    .val("");

                $("#mensaje")
                    .text("Estado actualizado correctamente.");

            } else {

                $("#mensaje")
                    .text(respuesta.message);

            }

        },

        error: function (xhr) {

            console.error(xhr);

            $("#mensaje")
                .text("No se ha podido actualizar el estado.");

        },

        complete: function () {

            boton
                .prop("disabled", false)
                .text("Guardar");

        }

    });

});

Una funcionalidad sencilla con una arquitectura importante

A primera vista, modificar un texto del perfil puede parecer una funcionalidad extremadamente sencilla.

Sin embargo, detrás de ese pequeño cambio existen varias capas trabajando conjuntamente:

INTERFAZ
HTML + CSS
   ↓
INTERACCIÓN
jQuery
   ↓
COMUNICACIÓN
AJAX / HTTP
   ↓
BACKEND
PHP
   ↓
PERSISTENCIA
MySQL
   ↓
RESPUESTA
JSON
   ↓
INTERFAZ
Actualización del DOM

Esta arquitectura es un ejemplo clásico de cómo una aplicación web puede actualizar únicamente una pequeña parte de su interfaz sin necesidad de volver a cargar todo el documento.

¿Y qué ocurre con el mensaje “¿Qué piensas?”?

Podemos utilizar el mensaje:

¿Qué piensas?

como estado predeterminado cuando el usuario todavía no tiene ningún estado almacenado.

Por ejemplo, al recuperar el perfil:

if (empty($usuario['estado'])) {
    $estado = "¿Qué piensas?";
} else {
    $estado = $usuario['estado'];
}

De esta manera el comportamiento resulta natural:

Usuario nuevo
     ↓
¿Qué piensas?

Usuario introduce:
"Trabajando en un nuevo proyecto"
     ↓
Guardar
     ↓
Base de datos
     ↓
Estado actualizado
     ↓
"Trabajando en un nuevo proyecto"

El resultado final

El objetivo de esta técnica es conseguir una experiencia mucho más fluida para el usuario.

En lugar de:

Editar estado
     ↓
Enviar formulario
     ↓
Esperar
     ↓
Recargar página
     ↓
Volver a mostrar perfil

tenemos:

Editar estado
     ↓
AJAX
     ↓
Guardar
     ↓
Actualizar interfaz
     ↓
Continuar trabajando

El cambio puede parecer pequeño, pero este patrón es fundamental en el desarrollo de interfaces web dinámicas.

Conclusión

Actualizar el estado de un perfil sin recargar la página es un ejemplo sencillo de una arquitectura basada en comunicación asíncrona entre el navegador y el servidor.

Utilizando jQuery y AJAX podemos capturar la acción del usuario y enviar el nuevo estado al backend. El servidor se encarga de validar los datos, comprobar la identidad y los permisos del usuario y almacenar la información en la base de datos.

Una vez completada la operación, el servidor devuelve una respuesta —preferiblemente en formato JSON— y JavaScript utiliza esa información para actualizar únicamente la parte necesaria del DOM.

El resultado es una interfaz más rápida, fluida y agradable de utilizar, sin necesidad de recargar constantemente la página.

Y aunque el ejemplo se centra en un simple estado de perfil, exactamente el mismo patrón puede utilizarse para construir funcionalidades mucho más complejas: editar perfiles, actualizar preferencias, votar, marcar favoritos, enviar comentarios, cargar notificaciones, modificar configuraciones o interactuar con cualquier otro elemento de una aplicación web de forma asíncrona.


Vídeo de demostración:

En el vídeo podemos ver el funcionamiento de la interfaz y cómo el estado del perfil se modifica dinámicamente sin necesidad de realizar una recarga completa de la página.

Visitas: 58

Website |  + posts

Automation & Data Specialist | Web Development | Data Processing & Integration

Deja un comentario