Hola.
Hoy vamos a ver cómo podemos editar nuestra propia información sin recargar la página y conseguir que el cambio se refleje inmediatamente tanto en la interfaz como en nuestra base de datos.
La idea es sencilla: el usuario modifica un dato, pulsa guardar y, en lugar de enviar el formulario y recargar toda la página, enviamos únicamente la información que ha cambiado al servidor.
El vídeo muestra precisamente el resultado que buscamos: modificar un dato y verlo actualizado inmediatamente, sin necesidad de abandonar la página.
¿Qué estamos haciendo realmente?
Aunque visualmente parece que simplemente estamos editando un campo, por detrás tenemos varias piezas trabajando conjuntamente.
El flujo sería aproximadamente este:
Usuario modifica un dato
↓
JavaScript detecta el cambio
↓
JavaScript envía los datos
↓
Petición HTTP asíncrona
↓
PHP recibe la información
↓
PHP valida los datos
↓
UPDATE en MySQL
↓
Servidor devuelve una respuesta
↓
JavaScript recibe la respuesta
↓
Actualizamos la interfaz
↓
Sin recargar la página
La clave está precisamente en esa comunicación asíncrona.
¿Qué significa editar de forma asíncrona?
Tradicionalmente, cuando enviamos un formulario, el navegador realiza una petición al servidor y recibe una nueva página:
Formulario ↓ POST ↓ Servidor ↓ Nueva página HTML ↓ Recarga del navegador
En nuestro caso queremos evitar esa recarga.
JavaScript puede realizar la petición en segundo plano utilizando tecnologías como Fetch API o AJAX mediante jQuery.
Así podemos enviar únicamente los datos necesarios:
Campo modificado ID del registro Nuevo valor
El servidor procesa la petición y nos devuelve el resultado.
Un ejemplo sencillo
Supongamos que tenemos una tabla de usuarios:
CREATE TABLE usuarios (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
estado VARCHAR(50) NOT NULL
);
Y queremos permitir que el usuario pueda modificar su estado.
Podríamos mostrar algo tan sencillo como:
<div class="usuario">
<label for="estado">Estado</label>
<input
type="text"
id="estado"
name="estado"
value="Disponible"
>
<button type="button" id="guardarEstado">
Guardar
</button>
<span id="mensaje"></span>
</div>
El botón no envía ningún formulario tradicional.
Será JavaScript quien se encargue de realizar la petición.
Detectando la acción con JavaScript
Podemos utilizar la API fetch(), que actualmente está disponible en los navegadores modernos y evita depender de jQuery para una tarea tan sencilla.
const boton = document.querySelector('#guardarEstado');
const campo = document.querySelector('#estado');
const mensaje = document.querySelector('#mensaje');
boton.addEventListener('click', async () => {
const estado = campo.value.trim();
if (!estado) {
mensaje.textContent = 'El estado no puede estar vacío.';
return;
}
try {
const response = await fetch('actualizar.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
estado: estado
})
});
const data = await response.json();
if (data.success) {
mensaje.textContent = 'Información actualizada.';
} else {
mensaje.textContent = data.message;
}
} catch (error) {
console.error(error);
mensaje.textContent = 'No se ha podido actualizar la información.';
}
});
Aquí ocurre prácticamente toda la magia del lado del cliente.
Cuando pulsamos Guardar, JavaScript obtiene el valor del campo y realiza una petición POST a nuestro archivo PHP.
¿Qué estamos enviando al servidor?
En este ejemplo enviamos un objeto JSON:
{
"estado": "Disponible"
}
Podríamos enviar más información si fuese necesario:
{
"id": 25,
"campo": "estado",
"valor": "Disponible"
}
Pero aquí aparece una cuestión fundamental:
Que JavaScript nos envíe un dato no significa que debamos confiar en él.
Todo lo que llega desde el navegador debe considerarse información potencialmente manipulable.
Recibiendo la información en PHP
En nuestro archivo actualizar.php podemos leer el cuerpo de la petición:
<?php
header('Content-Type: application/json; charset=utf-8');
require_once 'conn.php';
$data = json_decode(
file_get_contents('php://input'),
true
);
$estado = trim($data['estado'] ?? '');
if ($estado === '') {
echo json_encode([
'success' => false,
'message' => 'El estado no puede estar vacío.'
]);
exit;
}
Primero indicamos que nuestra respuesta será JSON:
header('Content-Type: application/json; charset=utf-8');
Después obtenemos el contenido enviado mediante php://input y lo convertimos desde JSON a un array de PHP.
Actualizando MySQL
Una vez validado el dato, podemos realizar el UPDATE.
$sql = "UPDATE usuarios
SET estado = :estado
WHERE id = :id";
$stmt = $dbconn->prepare($sql);
$stmt->execute([
':estado' => $estado,
':id' => $id
]);
Y aquí tenemos otro punto importante: consultas preparadas.
No debemos construir una consulta concatenando directamente los valores recibidos desde JavaScript.
Esto:
$sql = "UPDATE usuarios SET estado = '$estado' WHERE id = $id";
es una mala práctica.
Es preferible utilizar parámetros:
$sql = "UPDATE usuarios
SET estado = :estado
WHERE id = :id";
De esta manera dejamos que PDO gestione los valores y reducimos el riesgo de inyección SQL.
La respuesta del servidor
Una vez realizada la actualización, PHP puede devolver una respuesta JSON:
echo json_encode([
'success' => true,
'message' => 'Información actualizada correctamente.'
]);
JavaScript recibe esa respuesta:
const data = await response.json();
Y puede actuar en consecuencia:
if (data.success) {
mensaje.textContent = data.message;
}
Lo importante aquí es que no hemos recargado la página.
Actualizar también la interfaz
Supongamos que tenemos un texto que muestra el estado actual:
<span id="estadoActual">Disponible</span>
Después de actualizar correctamente la base de datos podemos modificar el DOM:
document.querySelector('#estadoActual').textContent = estado;
De esta manera conseguimos algo muy importante:
El cambio se produce tanto en la base de datos como visualmente en la página.
El usuario no necesita pulsar F5, recargar la página ni abandonar el formulario.
Pero cuidado: actualizar el DOM no actualiza la base de datos
Este detalle merece especial atención.
Modificar el contenido HTML mediante JavaScript:
element.textContent = 'Disponible';
no significa que hayamos guardado nada en MySQL.
Solamente hemos cambiado lo que aparece en el navegador.
Para que el dato sea persistente necesitamos realizar todo el proceso:
JavaScript ↓ HTTP POST ↓ PHP ↓ MySQL UPDATE ↓ Respuesta OK ↓ JavaScript ↓ Actualizar DOM
Esta separación entre interfaz y persistencia es fundamental para entender cómo funcionan muchas aplicaciones web modernas.
¿Y si la actualización falla?
También debemos contemplar este escenario.
Imaginemos que el servidor está caído, la conexión con MySQL falla o la consulta devuelve un error.
No deberíamos mostrar al usuario:
¡Guardado correctamente!
si realmente no se ha guardado nada.
Por eso la interfaz debe esperar la respuesta del servidor:
if (data.success) {
mensaje.textContent = 'Guardado correctamente.';
} else {
mensaje.textContent = 'No se ha podido guardar el cambio.';
}
Y además debemos controlar los errores de red:
try {
// petición
} catch (error) {
console.error(error);
mensaje.textContent =
'No se ha podido conectar con el servidor.';
}
Evitar dobles envíos
Hay otro pequeño problema que aparece rápidamente en este tipo de interfaces.
El usuario puede pulsar el botón varias veces mientras la petición todavía está procesándose.
Podemos desactivarlo temporalmente:
boton.disabled = true;
try {
const response = await fetch('actualizar.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
estado: campo.value.trim()
})
});
const data = await response.json();
// Procesamos la respuesta
} finally {
boton.disabled = false;
}
Es un detalle pequeño, pero mejora bastante la experiencia de usuario y evita peticiones innecesarias.
Seguridad: no debemos confiar en el ID enviado
Si nuestra aplicación permite editar información de usuarios, existe un aspecto todavía más importante.
No basta con recibir un id y ejecutar:
UPDATE usuarios SET estado = ... WHERE id = ...;
También tenemos que comprobar que el usuario que realiza la petición tiene permiso para modificar ese registro.
Por ejemplo, un usuario podría intentar modificar manualmente la petición y cambiar:
{
"id": 25
}
por:
{
"id": 26
}
Si nuestro PHP no comprueba permisos, podríamos estar permitiendo que un usuario modifique información que no le corresponde.
Por eso, en una aplicación real, la consulta debería estar relacionada con la identidad del usuario autenticado o con los permisos correspondientes.
También debemos validar en el servidor
La validación realizada mediante JavaScript es útil para mejorar la experiencia de usuario, pero no es una medida de seguridad.
Un usuario puede desactivar JavaScript, modificar la petición o utilizar directamente herramientas como cURL o Postman.
Por eso debemos validar nuevamente en PHP:
- Que el usuario está autenticado.
- Que tiene permisos para modificar el dato.
- Que el valor recibido tiene el formato esperado.
- Que el registro existe.
- Que la operación está permitida.
El navegador es un cliente. El servidor es quien debe tomar la decisión final.
Una evolución natural: edición directamente sobre el texto
Una vez que tenemos funcionando este mecanismo, podemos ir un paso más allá.
En lugar de mostrar siempre un campo de texto y un botón, podemos hacer que el usuario vea directamente:
Estado: Disponible
y que al pulsar sobre él se transforme temporalmente en:
[ Disponible ] [Guardar]
Esto es lo que normalmente conocemos como inline editing o edición en línea.
El concepto es exactamente el mismo:
Texto ↓ Modo edición ↓ Usuario modifica ↓ Guardar ↓ Fetch / AJAX ↓ Servidor ↓ Base de datos ↓ Respuesta ↓ Texto actualizado
Es una técnica especialmente útil en paneles de administración, perfiles de usuario, gestores de contenidos, CRM y aplicaciones internas.
¿Fetch o AJAX con jQuery?
Si este artículo se escribió originalmente utilizando jQuery, probablemente encontremos código basado en:
$.ajax({
url: 'actualizar.php',
type: 'POST',
data: {
estado: estado
}
});
Y sigue siendo perfectamente válido en proyectos que ya utilizan jQuery.
Sin embargo, para un proyecto nuevo podemos utilizar directamente la Fetch API, que forma parte del navegador y nos permite realizar peticiones HTTP sin añadir una dependencia adicional.
La idea no cambia:
jQuery AJAX ─────┐
├──→ HTTP → PHP → MySQL
Fetch API ──────┘
Lo importante no es tanto la herramienta concreta como comprender el flujo de datos.
¿Por qué resulta tan útil?
Este patrón permite construir interfaces mucho más fluidas.
En lugar de:
Editar ↓ Enviar formulario ↓ Recargar página ↓ Volver a localizar el dato
tenemos:
Editar ↓ Guardar ↓ Respuesta del servidor ↓ Cambio inmediato en pantalla
La diferencia para el usuario es enorme, especialmente cuando tenemos muchas operaciones pequeñas que realizar.
Conclusión
Editar información sin recargar la página no consiste simplemente en esconder un formulario y utilizar JavaScript.
Estamos construyendo una pequeña comunicación asíncrona entre navegador, servidor y base de datos:
NAVEGADOR
│
│ POST / Fetch
↓
SERVIDOR
│
│ UPDATE
↓
BASE DE DATOS
│
│ Resultado
↓
SERVIDOR
│
│ JSON
↓
NAVEGADOR
│
↓
Actualización del DOM
Y ahí está realmente la gracia del asunto.
El usuario solamente ve que ha cambiado un dato sin recargar la página. Pero por debajo hemos conseguido que la interfaz y la persistencia de datos estén sincronizadas.
Una vez dominado este patrón, podemos utilizar exactamente la misma técnica para editar perfiles, estados, configuraciones, comentarios, productos, registros administrativos o prácticamente cualquier información que necesitemos modificar desde una interfaz web.
Rápido para el usuario, eficiente para la aplicación y, siempre que validemos correctamente en el servidor, seguro.
Un saludo y nos vemos en el próximo artículo.
Visitas: 316
Automation & Data Specialist | Web Development | Data Processing & Integration
