CRUD es un acrónimo que representa las cuatro operaciones básicas que se realizan en las bases de datos:
Create (Crear): Insertar nuevos registros en una tabla.
Read (Leer): Consultar y recuperar datos de la base de datos.
Update (Actualizar): Modificar registros existentes en la base de datos.
Delete (Eliminar): Eliminar registros de la base de datos.
Estas operaciones son fundamentales en las aplicaciones web, ya que permiten interactuar con los datos de manera eficiente. La mayoría de las aplicaciones web, como sistemas de gestión, tiendas en línea o redes sociales, realizan operaciones CRUD para gestionar sus datos.
Casos de uso de una página de administración CRUD
Imaginemos una página de administración de empleados, que es el caso de uso en el que nos centraremos en este tema. Esta página permitirá a los administradores:
Ver la lista de empleados: Una tabla que muestre los empleados actuales.
Añadir nuevos empleados: Un formulario que permita ingresar nuevos datos de empleados.
Editar datos de los empleados: Un formulario que permita modificar los datos de los empleados existentes.
Eliminar empleados: Opción para eliminar empleados de la base de datos.
En la siguiente imagen, mostramos cómo se podría representar este flujo de operaciones en un diagrama de casos de uso.
Diagrama de Casos de Uso en Mermaid
Diagrama de Casos de Uso
Este diagrama ilustra las operaciones CRUD en la página de administración de empleados.
%%{init: {"themeVariables": {"primaryColor": "#4E8AF4", "edgeLabelBackground":"#ffffff", "tertiaryColor": "#f9f9f9"}}}%%
graph TB
A[Administrar Empleados] --> B[Ver lista de empleados]
A[Administrar Empleados] --> C[Añadir nuevo empleado]
A[Administrar Empleados] --> D[Editar datos de empleado]
A[Administrar Empleados] --> E[Eliminar empleado]
B --> F[Consultar empleados]
C --> G[Formulario para crear]
D --> H[Formulario para editar]
E --> I[Confirmación de eliminación]
Este diagrama visualiza cómo las operaciones CRUD se traducen en funcionalidades en la interfaz de usuario de una aplicación web.
Estructura de la página de administración
Para empezar, necesitamos tener una visión clara de cómo se verá la página de administración. El diseño debe permitir que los administradores interactúen fácilmente con los empleados, ya sea para agregar nuevos, ver los existentes, actualizarlos o eliminarlos.
Vamos a estructurar la página en los siguientes pasos:
Vista de los empleados: Esta es la página principal donde se mostrarán todos los empleados en una tabla.
Formulario de creación de nuevo empleado: Un formulario donde el administrador pueda ingresar los datos del nuevo empleado.
Formulario de edición de empleado: Similar al formulario de creación, pero con los datos del empleado que se desean modificar.
Confirmación de eliminación: Un mecanismo para pedir confirmación antes de eliminar un registro.
Objetivos de la página CRUD
Interactividad: La página permitirá al usuario interactuar de forma intuitiva, sin recargar la página.
Validación de entradas: Tanto en el lado del cliente (HTML) como en el servidor (PHP), para asegurarnos de que los datos introducidos son correctos y seguros.
Facilidad de uso: Usaremos tablas para visualizar los datos, y formularios para editar y agregar empleados.
Resumen de la introducción
En este punto, hemos definido qué es CRUD y cómo se aplica en la página de administración de empleados. Hemos visto cómo estructuraremos la página y qué funcionalidades debemos implementar, desde la visualización de los empleados hasta la adición, edición y eliminación de registros.
Ahora, avanzaremos con el siguiente punto, que es la vista HTML donde crearemos la estructura básica de la página y organizaremos los datos.
3.7.2 Vista HTML - Estructura de la página
Estructura básica de la página
La estructura de nuestra página de administración CRUD de empleados tendrá:
Una tabla para mostrar los empleados.
Filtros para buscar y ordenar los empleados por nombre, apellido, etc.
Botones de acción para editar, eliminar o añadir nuevos empleados.
1. Crear la tabla para visualizar empleados
La tabla será el centro de nuestra vista. Aquí se mostrarán todos los empleados de la base de datos. La estructura básica de la tabla incluirá columnas como: ID, Nombre, Apellido, fecha nacimiento, fecha de contratación y género etc. Además, proporcionaremos botones de acción en cada fila para editar o eliminar a cada empleado. los campos que necesitamos incluir son:
<!DOCTYPE html><htmllang="es"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Administración de Empleados</title><linkrel="stylesheet"href="styles.css"></head><body><h1>Administración de Empleados</h1><!-- Botón para agregar nuevo empleado --><button>Añadir Nuevo Empleado</button><!-- Tabla de empleados --><tableid="empleados"><thead><tr><th>ID</th><th>Nombre</th><th>Apellido</th><th>Fecha de Nacimiento</th><th>Fecha de Contratación</th><th>Género</th><th>Acciones</th></tr></thead><tbody><!-- Filas de empleados serán generadas aquí --></tbody></table><scriptsrc="scripts.js"></script></body></html>
El archivo CSS definirá el diseño y estilo de la página, incluidos los formularios, la tabla y la ventana modal.
/* Estilos generales */body{font-family:Arial,sans-serif;margin:20px;}/* Estilos de la tabla */table{width:100%;border-collapse:collapse;margin-top:20px;}table,th,td{border:1pxsolid#ddd;}th,td{padding:8px;text-align:left;}th{background-color:#f2f2f2;}tr:hover{background-color:#f1f1f1;}/* Estilos de los botones */button{padding:10px15px;margin:5px;cursor:pointer;}button:hover{background-color:#ddd;}
El archivo JS manejará la interacción con los elementos de la página, como abrir y cerrar el formulario, realizar la ordenación de la tabla y manejar las acciones de editar y eliminar.
// Función para confirmar la eliminación de un empleadofunctionconfirmarEliminacion(id){if(confirm("¿Estás seguro de que deseas eliminar este empleado?")){// Realizar la eliminación (esto debería ser gestionado por PHP)alert("Empleado con ID "+id+" eliminado");}}
Explicación de la estructura HTML:
Tabla de empleados: La tabla ahora incluye las columnas correctas: ID, Nombre, Apellido, Fecha de Nacimiento, Fecha de Contratación, y Género. Además, la columna "Acciones" contendrá los botones para editar o eliminar un empleado.
Filtros y ordenación:
Los filtros y campos de ordenación de momento no se muestran. Lo dejamos para más adelante.
Formulario de creación/edición:
El formulario de momento no está en la página, lo añadiremos más adelante, en una ventana modal.
El formulario permite al administrador agregar o editar empleados.
Los campos del formulario son: ID (deshabilitado, se genera automáticamente o se puede ingresar si es necesario), Nombre, Apellido, Fecha de Nacimiento, Fecha de Contratación y Género.
El formulario se presentará en una ventana modal cuando el administrador haga clic en el botón "Añadir Nuevo Empleado".
CSS y JS
Este es el primer paso de la página, centrado en la estructura HTML. El siguiente paso sería integrar la lógica de PHP para llenar la tabla con los datos desde la base de datos y manejar las operaciones de CRUD.
A continuación, pasaremos a la parte de llenado de la tabla con los datos de la base de datos, lo que se hará en un paso posterior cuando introduzcamos los scripts de PHP y conectemos la base de datos a la interfaz HTML.
3.7.3 Mostrar los empleados en una tabla
En este punto, vamos a explicar cómo llenar la tabla de empleados con datos desde la base de datos y cómo manejar las interacciones con los botones de acción (editar y eliminar).
Objetivos:
Conectar con la base de datos para obtener los empleados.
Mostrar los datos en la tabla HTML.
Implementar funcionalidades como editar y eliminar usando botones de acción en la tabla.
Aplicar seguridad en la consulta para evitar SQL Injection.
1. Conexión a la base de datos y obtener los empleados
Para mostrar los empleados, necesitamos conectarnos a la base de datos, hacer una consulta SELECT a la tabla employees y recuperar los datos. Los resultados de esta consulta se mostrarán en la tabla HTML.
<?php// Conexión a la base de datos$conexion=newmysqli("localhost","root","","employees");if($conexion->connect_error){die("Conexión fallida: ".$conexion->connect_error);}// Consulta para obtener todos los empleados$query="SELECT emp_no, first_name, last_name, birth_date, hire_date, gender FROM employees";$resultado=$conexion->query($query);if($resultado->num_rows>0){while($empleado=$resultado->fetch_assoc()){echo"<tr>";echo"<td>".$empleado['emp_no']."</td>";echo"<td>".$empleado['first_name']."</td>";echo"<td>".$empleado['last_name']."</td>";echo"<td>".$empleado['birth_date']."</td>";echo"<td>".$empleado['hire_date']."</td>";echo"<td>".$empleado['gender']."</td>";echo"<td> <button onclick='editarEmpleado(".$empleado['emp_no'].")'>Editar</button> <button onclick='eliminarEmpleado(".$empleado['emp_no'].")'>Eliminar</button> </td>";echo"</tr>";}}else{echo"<tr><td colspan='7'>No hay empleados para mostrar.</td></tr>";}$conexion->close();?>
<?php// Conexión a la base de datos$conexion=mysqli_connect("localhost","root","","employees");if(!$conexion){die("Conexión fallida: ".mysqli_connect_error());}// Consulta para obtener todos los empleados$query="SELECT emp_no, first_name, last_name, birth_date, hire_date, gender FROM employees";$resultado=mysqli_query($conexion,$query);if(mysqli_num_rows($resultado)>0){while($empleado=mysqli_fetch_assoc($resultado)){echo"<tr>";echo"<td>".$empleado['emp_no']."</td>";echo"<td>".$empleado['first_name']."</td>";echo"<td>".$empleado['last_name']."</td>";echo"<td>".$empleado['birth_date']."</td>";echo"<td>".$empleado['hire_date']."</td>";echo"<td>".$empleado['gender']."</td>";echo"<td> <button onclick='editarEmpleado(".$empleado['emp_no'].")'>Editar</button> <button onclick='eliminarEmpleado(".$empleado['emp_no'].")'>Eliminar</button> </td>";echo"</tr>";}}else{echo"<tr><td colspan='7'>No hay empleados para mostrar.</td></tr>";}// Cerrar la conexiónmysqli_close($conexion);?>
Vamos a analizar el código:
Conexión a la base de datos: Se establece una conexión a la base de datos utilizando mysqli_connect() o new mysqli(), lo hemos visto en temas anteriores.
Consulta SQL: Se realiza una consulta SELECT para obtener todos los empleados de la tabla employees, en este caso sacamos todos los empleados. Sin filtro.
Objeto de resultado: Se verifica si hay resultados y se recorren con un bucle while, generando dinámicamente las filas <tr> para cada empleado. Hay que ver como se crea una fila en la tabla por cada empleado, y una celda por cada campo del empleado.
-- Botones de acción: En cada fila, se incluyen botones Editar y Eliminar que llamarán a las funciones editarEmpleado() y eliminarEmpleado() respectivamente. Estas funciones se implementarán más adelante.
En este código hay que resaltar como pasamos como parámetro a editarEmpleado y eliminarEmpleado el emp_no, que es el id del empleado. Esto es importante para poder identificar al empleado que queremos editar o eliminar. Por tabto cada fila tendrá una llamada a las funciones pero con el id del empleado correspondiente.
PDO:
Código PHP para obtener empleados con PDO
<?phptry{$conexion=newPDO("mysql:host=localhost;dbname=employees","root","");$conexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);// Consulta para obtener todos los empleados$query="SELECT emp_no, first_name, last_name, birth_date, hire_date, gender FROM employees";$stmt=$conexion->query($query);if($stmt->rowCount()>0){while($empleado=$stmt->fetch(PDO::FETCH_ASSOC)){echo"<tr>";echo"<td>".$empleado['emp_no']."</td>";echo"<td>".$empleado['first_name']."</td>";echo"<td>".$empleado['last_name']."</td>";echo"<td>".$empleado['birth_date']."</td>";echo"<td>".$empleado['hire_date']."</td>";echo"<td>".$empleado['gender']."</td>";echo"<td> <button onclick='editarEmpleado(".$empleado['emp_no'].")'>Editar</button> <button onclick='eliminarEmpleado(".$empleado['emp_no'].")'>Eliminar</button> </td>";echo"</tr>";}}else{echo"<tr><td colspan='7'>No hay empleados para mostrar.</td></tr>";}}catch(PDOException$e){echo"Error: ".$e->getMessage();}$conexion=null;?>
En este ejemplo el análisis es igual que el anterior solo que utilizamos PDO para conectarnos a la base de datos. La diferencia principal es que PDO permite una mejor gestión de errores y es más flexible al trabajar con diferentes bases de datos.
2. Mostrar los datos en la tabla HTML
Los datos que obtenemos de la base de datos deben ser mostrados en el cuerpo de la tabla en el HTML. El código PHP que hemos mostrado anteriormente generará dinámicamente las filas <tr> para cada empleado.
Dentro de cada fila, se mostrarán los datos de cada empleado: ID, Nombre, Apellido, Fecha de Nacimiento, Fecha de Contratación, y Género.
Además, se agregarán botones Editar y Eliminar en cada fila para permitir la modificación o eliminación de los registros. Estos botones llamarán a las funciones editarEmpleado() y eliminarEmpleado() que se implementarán más adelante.
3. Interacción con los botones (Editar y Eliminar)
Cuando el administrador haga clic en el botón Editar, se abrirá el formulario con los datos del empleado para que pueda modificarlos. Para Eliminar, se pedirá confirmación antes de proceder.
Función de Editar:
El botón de Editar pasa el emp_no (ID del empleado) a la función editarEmpleado(). Esto puede abrir el formulario modal con los datos correspondientes del empleado que se desea editar.
Función de Eliminar:
El botón de Eliminar también pasa el emp_no del empleado y ejecuta la función eliminarEmpleado(). Esta función pedirá confirmación antes de eliminar el registro del empleado.
Implementación de las funciones.
De momento vamos a añadir las funciones de editar y eliminar en el fichero JavaScript, aunque no las implementaremos del todo. Más adelante veremos como implementar la lógica de edición y eliminación. Ahora nos conformarmos con que aparezca un alert con la acción que se va a realizar y el id del empleado.
// Función para editar un empleadofunctioneditarEmpleado(emp_no){alert("Editando empleado con ID: "+emp_no);// Aquí puedes agregar la lógica para llenar el formulario con los datos del empleado// y mostrar la ventana modal}// Función para eliminar un empleadofunctioneliminarEmpleado(emp_no){if(confirm("¿Estás seguro de que deseas eliminar el empleado con ID: "+emp_no+"?")){alert("Empleado con ID "+emp_no+" eliminado");// Aquí puedes agregar la lógica para eliminar el empleado de la base de datos}}
Problemas por la cantidad de empleados
Como habrás podido comprobar (puedes mirarlo con select count(*) from employees), la tabla de empleados tiene una gran cantidad de registros. Esto puede hacer que la carga inicial de la página sea lenta.
para evitar esto, podemos implementar paginación o cargar los datos de forma asíncrona (AJAX) para mejorar la experiencia del usuario. Es recomendable que la tabla no cargue todos los empleados de golpe, sino que se carguen por partes. Esto lo veremos más adelante.
Ahora, para hacer más fácil la visualización vamos a limitar la cantidad de empleados que se muestran en la tabla. Para ello, podemos usar la cláusula LIMIT en la consulta SQL. Por ejemplo, si queremos mostrar solo los primeros 100 empleados, podemos modificar la consulta de la siguiente manera:
Ahora mismo, la página de administración de empleados tiene la siguiente funcionalidad:
Conexión a la base de datos: Se conecta a la base de datos y obtiene los empleados.
Mostrar empleados: Los empleados se muestran en una tabla HTML generada dinámicamente desde PHP.
Botones de acción: Se han agregado botones para editar y eliminar empleados, aunque la lógica de edición y eliminación aún no está implementada.
Nota: Hemos limitado la cantidad de empleados que se muestran en la tabla a 100 para mejorar la carga inicial de la página. Esto es solo un ejemplo y puedes ajustar el límite según tus necesidades.
Esta es la vista que tenemos hasta ahora:
Vista del formulario modal que utilziaremos para inserciones y modificaciones:
Vista del mensaje que aparece cuando pulsamos los botones de ordenaar (de momento solo un alert)
Resumen
En este punto hemos cubierto:
Conexión a la base de datos para obtener los empleados.
Mostrar los empleados en una tabla HTML generada dinámicamente desde PHP.
Botones de acción: Agregar botones para editar y eliminar empleados.
¡Excelente! Ya está funcionando, la tabla está mostrando los empleados correctamente. La limitación de registros es una excelente práctica, podrémos añadir paginación más adelante para mejorar la eficiencia y la experiencia del usuario.
3.7.4 Mostrar datos del empleado (ventana modal)
Vamos a implementar la ventana modal para mostrar los detalles de un empleado cuando el administrador haga clic en el botón de ver o editar.
La ventana modal es una excelente forma de mostrar la información sin necesidad de recargar la página o navegar a una nueva.
Objetivos:
Crear una ventana modal que muestre los detalles del empleado seleccionado.
La ventana se abrirá al hacer clic en el botón Ver o Editar.
Podremos ver más información detallada del empleado y, en el caso de la edición, modificar esos datos.
Estructura de la ventana modal
1. Mostrar los datos del empleado en la ventana modal
La ventana modal mostrará un formulario con los campos de datos del empleado que se seleccionó. Si es una edición, los campos estarán prellenados con los datos actuales.
2. Código HTML de la ventana modal (ya incluido)
Tenemos que incluir del siguiente código de la ventana modal en el HTML anterior. Tenemos un formulario con los diferentes campos necesarios, todos los campos son obligatorios y el ID del empleado está deshabilitado para evitar que se modifique. Para las fechas hemos utilizado el tipo date, que permite seleccionar la fecha de una manera más amigable.
<!-- Ventana modal para agregar/editar empleado --><divid="modalFormulario"class="modal"><divclass="modal-content"><spanclass="close"onclick="cerrarFormulario()">×</span><h2>Formulario de Empleado</h2><formid="formEmpleado"method="post"><labelfor="emp_id">ID:</label><inputtype="text"id="emp_id"name="emp_id"disabled><labelfor="nombre">Nombre:</label><inputtype="text"id="nombre"name="nombre"required><labelfor="apellido">Apellido:</label><inputtype="text"id="apellido"name="apellido"required><labelfor="fecha_nacimiento">Fecha de Nacimiento:</label><inputtype="date"id="fecha_nacimiento"name="fecha_nacimiento"required><labelfor="fecha_contratacion">Fecha de Contratación:</label><inputtype="date"id="fecha_contratacion"name="fecha_contratacion"required><labelfor="genero">Género:</label><selectid="genero"name="genero"required><optionvalue="M">Masculino</option><optionvalue="F">Femenino</option><optionvalue="O">Otro</option></select><buttontype="submit">Guardar</button><buttontype="button"onclick="cerrarFormulario()">Cancelar</button></form></div></div>
Este código ya incluye la ventana modal que contiene el formulario para agregar o editar empleados. El funcionamiento de la ventana modal está basado en reglas css. Puedes encontrar los estilos en el fichero css cargado al inicio. Si no lo has trabajado con anterioridad te recomiento que hagas pruebas en una página nueva HTML para comprender su funcionamiento y lo que hacen las reglas.
/* Estilos de la ventana modal */.modal{display:none;position:fixed;z-index:1;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);}.modal-content{background-color:white;margin:15%auto;padding:20px;border:1pxsolid#888;width:80%;}.close{color:#aaa;float:right;font-size:28px;font-weight:bold;}.close:hover,.close:focus{color:black;text-decoration:none;cursor:pointer;}
Son dos clases, .modal y .modal-content, que controlan la apariencia de la ventana modal. La clase .modal controla el fondo oscuro y la posición de la ventana, mientras que .modal-content controla el contenido de la ventana modal. La clase .close se utiliza para el botón de cerrar la ventana modal.
3. Función para llenar los datos del empleado en el formulario modal
Cuando el administrador haga clic en el botón de Ver o Editar, se debe llenar el formulario con los datos correspondientes del empleado.
En nuestra aplicación ya tenemos implementado el evento onclik del botón de editar que llama a la función editarEmpleado(id). Ahora vamos a reemplazar la función de que tenemos (ahora solo muestra un alert) por la función siguiente.
Función de JavaScript para mostrar el formulario con los datos del empleado:
Esta función se encargará de llenar el formulario con los datos del empleado seleccionado. Utilizaremos AJAX para obtener los datos del empleado desde el servidor sin recargar la página. Utilizaremos el método GET para pasar el id del empleado al script php. En otras ocasiones utilizaremos POST para poder enviar los datos del formulario al servidor.
// Función para llenar el formulario con los datos del empleadofunctioneditarEmpleado(emp_id){// Llamar al servidor para obtener los datos del empleado (esto debe hacerse con una solicitud AJAX)// Suponemos que el servidor devuelve los datos en formato JSONfetch('getEmpleado.php?id='+emp_id).then(response=>response.json()).then(data=>{// Llenar los campos del formulario modal con los datosdocument.getElementById('emp_id').value=data.emp_no;document.getElementById('nombre').value=data.first_name;document.getElementById('apellido').value=data.last_name;document.getElementById('fecha_nacimiento').value=data.birth_date;document.getElementById('fecha_contratacion').value=data.hire_date;document.getElementById('genero').value=data.gender;// Mostrar la ventana modalmostrarFormulario();}).catch(error=>console.error('Error al obtener los datos del empleado:',error));}
Esta función llama (AJAX utilizando fetch) a un scriptphp al que llamaremos getEmpledo.php y que tenemos implementado en el punto siguiente. De estamanera evitamos tener que recargar toda la página del navegador y solicitamos al servidor los datos del empleado que queremos editar. El script nos devolverà un json con todos los datos del empleado.
Para que funcione la ventana modal tenemos que implementar la función mostrarFormulario() que se encargará de mostrar la ventana modal. Esta función simplemente cambiará el estilo de la ventana modal para que sea visible. Y cerrarFormulario() que se encargará de ocultar la ventana modal.
// Función para mostrar la ventana modalfunctionmostrarFormulario(){document.getElementById('modalFormulario').style.display='block';}// Función para cerrar la ventana modalfunctioncerrarFormulario(){document.getElementById('modalFormulario').style.display='none';}
4. PHP para obtener los datos del empleado
El siguiente paso es crear un archivo PHP (por ejemplo, getEmpleado.php) que recibirá un ID de empleado, obtendrá sus datos de la base de datos y devolverá la información en formato JSON. En este caso vamos a utilizar el método GET para obtener el ID del empleado.
<?php// Conexión a la base de datos$conexion=newmysqli("localhost","root","","employees");if($conexion->connect_error){die("Conexión fallida: ".$conexion->connect_error);}// Validar si se ha proporcionado el ID del empleadoif(!isset($_GET['id'])){echojson_encode(['error'=>'ID de empleado no proporcionado']);exit;}// Validar que el ID del empleado es un número enteroif(!filter_var($_GET['id'],FILTER_VALIDATE_INT)){echojson_encode(['error'=>'ID de empleado inválido']);exit;}// Obtener el ID del empleado$emp_id=$_GET['id'];// Consulta para obtener el empleado$query="SELECT emp_no, first_name, last_name, birth_date, hire_date, gender FROM employees WHERE emp_no = ?";$stmt=$conexion->prepare($query);$stmt->bind_param("i",$emp_id);$stmt->execute();$result=$stmt->get_result();// Devolver los datos en formato JSONif($result->num_rows>0){$empleado=$result->fetch_assoc();echojson_encode($empleado);}else{echojson_encode(['error'=>'Empleado no encontrado']);}$stmt->close();$conexion->close();?>
<?php// Conexión a la base de datos utilizando PDOtry{$conexion=newPDO("mysql:host=localhost;dbname=employees","root","");$conexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);// Validar si se ha proporcionado el ID del empleadoif(!isset($_GET['id'])){echojson_encode(['error'=>'ID de empleado no proporcionado']);exit;}// Validar que el ID del empleado es un número enteroif(!filter_var($_GET['id'],FILTER_VALIDATE_INT)){echojson_encode(['error'=>'ID de empleado inválido']);exit;}// Obtener el ID del empleado$emp_id=$_GET['id'];// Consulta para obtener el empleado$query="SELECT emp_no, first_name, last_name, birth_date, hire_date, gender FROM employees WHERE emp_no = :emp_id";$stmt=$conexion->prepare($query);// Vincular el parámetro$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);// Ejecutar la consulta$stmt->execute();// Verificar si se encontró un resultadoif($stmt->rowCount()>0){$empleado=$stmt->fetch(PDO::FETCH_ASSOC);echojson_encode($empleado);// Devolver los datos en formato JSON}else{echojson_encode(['error'=>'Empleado no encontrado']);}}catch(PDOException$e){echo"Error: ".$e->getMessage();}// Cerrar la conexión$conexion=null;?>
Este archivo getEmpleado.php recibe un ID de empleado, realiza una consulta a la base de datos y devuelve los datos del empleado en formato JSON para que el formulario modal se pueda completar.
Resumen del punto 3.7.4: Mostrar datos del empleado (ventana modal)
En este punto hemos cubierto:
Mostrar la ventana modal para mostrar los datos del empleado seleccionado.
JavaScript para llenar el formulario con los datos del empleado cuando se haga clic en el botón Editar.
PHP para obtener los datos del empleado desde la base de datos y devolverlos en formato JSON.
En el siguiente paso, vamos a implementar el proceso para editar los empleados y validar los datos tanto en el cliente (HTML) como en el servidor (PHP).
3.7.5 Editar datos del empleado
En este punto, vamos a permitir que el administrador pueda editar los datos de un empleado desde la misma página de administración, sin recargar la página. Utilizaremos AJAX para realizar la actualización de forma asíncrona y, de esta manera, no perder la vista actual ni recargar la tabla de empleados.
Objetivos:
Formulario de edición: Permitir que el administrador edite los datos de un empleado directamente desde un formulario en la ventana modal.
Validación de los datos: Validar los campos tanto en el cliente (HTML5 y JavaScript) como en el servidor (PHP).
Actualizar los datos: Realizar la actualización de los datos del empleado en la base de datos sin recargar la página.
Actualizar la fila en la tabla: Una vez que los datos se hayan actualizado, se reflejarán en la tabla de empleados sin tener que recargarla.
1. formulario modal
El formulario de edición se ha diseñado en una ventana modal. El objetivo es que, al hacer clic en el botón "Guardar", se envíen los datos del formulario al servidor sin recargar la página.
HTML del formulario:
El formulario para la edición es el mismo que ya tenemos implementado en el código anterior. Aquí lo incluimos nuevamente para referencia:
<!-- Formulario de Empleado (sin cambios) --><formid="formEmpleado"method="post"onsubmit="return false;"><labelfor="emp_id">ID:</label><inputtype="text"id="emp_id"name="emp_id"disabled><labelfor="nombre">Nombre:</label><inputtype="text"id="nombre"name="nombre"required><labelfor="apellido">Apellido:</label><inputtype="text"id="apellido"name="apellido"required><labelfor="fecha_nacimiento">Fecha de Nacimiento:</label><inputtype="date"id="fecha_nacimiento"name="fecha_nacimiento"required><labelfor="fecha_contratacion">Fecha de Contratación:</label><inputtype="date"id="fecha_contratacion"name="fecha_contratacion"required><labelfor="genero">Género:</label><selectid="genero"name="genero"required><optionvalue="M">Masculino</option><optionvalue="F">Femenino</option><optionvalue="O">Otro</option></select><buttontype="submit"onclick="guardarEmpleado()">Guardar</button><buttontype="button"onclick="cerrarFormulario()">Cancelar</button></form>
2. Enviar los datos con AJAX
La función guardarEmpleado() enviará los datos del formulario al servidor utilizando AJAX para que no se recargue la página.
Problema con emp_id
Nota: El campo emp_id está deshabilitado en el formulario, por tanto no se enviará al servidor. Para solucionarlo tenemos que modificar parte del código. En javascripten vez de utilizar FormData para enviar los datos, vamos a crear un objeto JSON con los datos del formulario y lo enviaremos al servidor. De esta manera, el campo emp_id se enviará correctamente. Si utilizamos FormData, el campo emp_id no se enviará porque está deshabilitado, y la acutualización fallará.
JavaScript con AJAX:
Código JavaScript para enviar los datos del formulario
// Función para guardar los datos del empleadofunctionguardarEmpleado(){constform=document.getElementById('formEmpleado');constemp_id=document.getElementById('emp_id').value;// Obtener el ID del empleadoconstnombre=document.getElementById('nombre').value;constapellido=document.getElementById('apellido').value;constfecha_nacimiento=document.getElementById('fecha_nacimiento').value;constfecha_contratacion=document.getElementById('fecha_contratacion').value;constgenero=document.getElementById('genero').value;// Crear un objeto con los datos a enviarconstdata={emp_id:emp_id,nombre:nombre,apellido:apellido,fecha_nacimiento:fecha_nacimiento,fecha_contratacion:fecha_contratacion,genero:genero};// const formData = new FormData(form);fetch('editarEmpleado.php',{method:'POST',headers:{'Content-Type':'application/json'// Especificamos que el contenido será JSON},body:JSON.stringify(data)// Convertimos el objeto a JSON}).then(response=>response.json()).then(data=>{if(data.success){// Si la actualización fue exitosa, actualizar la tabla sin recargar la páginaactualizarFila(data.empleado);cerrarFormulario();}else{// Si hay un error, mostrar el mensaje de erroralert(data.error||"Error al actualizar el empleado.");}}).catch(error=>{console.error('Error:',error);alert('Error en la actualización.');});}
En el código podemos ver como obtenemos los datos del formulario y los convertimos a un objeto JSON. Luego, utilizamos fetch para enviar una solicitud POST al archivo editarEmpleado.php. En la cabecera especificamos que el contenido será JSON y en el cuerpo enviamos el objeto convertido a JSON.
3. PHP para actualizar los datos sin recargar la página
En el archivo editarEmpleado.php, recibiremos los datos del formulario enviados por AJAX y actualizaremos la base de datos. Luego, devolveremos una respuesta JSON al cliente.
<?php// Conexión a la base de datos con MySQLi OO$host=getenv('MYSQL_HOST');$user=getenv('MYSQL_USER');$pass=getenv('MYSQL_PASSWORD');$db='employees';$conexion=newmysqli($host,$user,$pass,$db);// Verificar conexiónif($conexion->connect_error){echojson_encode(['success'=>false,'error'=>"Conexión fallida: ".$conexion->connect_error]);exit;}// Recibir los datos JSON enviados por AJAX$data=json_decode(file_get_contents("php://input"));if($data){$emp_id=$data->emp_id;$nombre=$data->nombre;$apellido=$data->apellido;$fecha_nacimiento=$data->fecha_nacimiento;$fecha_contratacion=$data->fecha_contratacion;$genero=$data->genero;// Validación de fechas$fecha_nacimiento_obj=newDateTime($fecha_nacimiento);$fecha_contratacion_obj=newDateTime($fecha_contratacion);$fecha_actual=newDateTime();$fecha_minima_nacimiento=clone$fecha_contratacion_obj;$fecha_minima_nacimiento->sub(newDateInterval('P18Y'));if($fecha_nacimiento_obj>$fecha_minima_nacimiento){echojson_encode(['success'=>false,'error'=>"La fecha de nacimiento debe ser al menos 18 años antes de la fecha de contratación."]);exit;}if($fecha_contratacion_obj>$fecha_actual){echojson_encode(['success'=>false,'error'=>"La fecha de contratación no puede ser posterior a la fecha actual."]);exit;}// Consulta preparada con MySQLi OO$query="UPDATE employees SET first_name = ?, last_name = ?, birth_date = ?, hire_date = ?, gender = ? WHERE emp_no = ?";$stmt=$conexion->prepare($query);if(!$stmt){echojson_encode(['success'=>false,'error'=>"Error en la preparación de la consulta: ".$conexion->error]);exit;}$stmt->bind_param("sssssi",$nombre,$apellido,$fecha_nacimiento,$fecha_contratacion,$genero,$emp_id);$stmt->execute();if($stmt->affected_rows>=0){$empleado=['emp_no'=>$emp_id,'first_name'=>$nombre,'last_name'=>$apellido,'birth_date'=>$fecha_nacimiento,'hire_date'=>$fecha_contratacion,'gender'=>$genero];echojson_encode(['success'=>true,'empleado'=>$empleado]);}else{echojson_encode(['success'=>false,'error'=>'No se actualizó ningún registro.']);}$stmt->close();}$conexion->close();?>
<?phptry{// Conexión a la base de datos con PDO$host=getenv('MYSQL_HOST');$user=getenv('MYSQL_USER');$pass=getenv('MYSQL_PASSWORD');$conexion=newPDO("mysql:host=$host;dbname=employees",$user,$pass);$conexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);// Recibir los datos JSON enviados por AJAX$data=json_decode(file_get_contents("php://input"));if($data){// Recibir los datos del formulario$emp_id=$data->emp_id;$nombre=$data->nombre;$apellido=$data->apellido;$fecha_nacimiento=$data->fecha_nacimiento;$fecha_contratacion=$data->fecha_contratacion;$genero=$data->genero;// Validación de fechas$fecha_nacimiento_obj=newDateTime($fecha_nacimiento);$fecha_contratacion_obj=newDateTime($fecha_contratacion);$fecha_actual=newDateTime();// Validar que la fecha de nacimiento sea al menos 18 años antes de la fecha de contratación$fecha_minima_nacimiento=$fecha_contratacion_obj->sub(newDateInterval('P18Y'));if($fecha_nacimiento_obj>$fecha_minima_nacimiento){echojson_encode(['success'=>false,'error'=>"La fecha de nacimiento debe ser al menos 18 años antes de la fecha de contratación."]);exit;}// Validar que la fecha de contratación no sea mayor que la fecha actualif($fecha_contratacion_obj>$fecha_actual){echojson_encode(['success'=>false,'error'=>"La fecha de contratación no puede ser posterior a la fecha actual."]);exit;}// Consulta para actualizar los datos$query="UPDATE employees SET first_name = :nombre, last_name = :apellido, birth_date = :fecha_nacimiento, hire_date = :fecha_contratacion, gender = :genero WHERE emp_no = :emp_id";// Ejecutar la consulta$stmt=$conexion->prepare($query);$stmt->bindParam(':nombre',$nombre,PDO::PARAM_STR);$stmt->bindParam(':apellido',$apellido,PDO::PARAM_STR);$stmt->bindParam(':fecha_nacimiento',$fecha_nacimiento,PDO::PARAM_STR);$stmt->bindParam(':fecha_contratacion',$fecha_contratacion,PDO::PARAM_STR);$stmt->bindParam(':genero',$genero,PDO::PARAM_STR);$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);$stmt->execute();// Devolver éxito y los datos actualizados$empleado=['emp_no'=>$emp_id,'first_name'=>$nombre,'last_name'=>$apellido,'birth_date'=>$fecha_nacimiento,'hire_date'=>$fecha_contratacion,'gender'=>$genero];echojson_encode(['success'=>true,'empleado'=>$empleado]);}}catch(PDOException$e){echojson_encode(['success'=>false,'error'=>$e->getMessage()]);}$conexion=null;?>
En este caso nuestro código PHP recibe los datos del formulario enviados por AJAX, realiza las validaciones necesarias (como la fecha de nacimiento y la fecha de contratación) y actualiza los datos del empleado en la base de datos. Luego, devuelve una respuesta JSON al cliente con el resultado de la operación. Las resuestas pueden ser:
success: true si la actualización fue exitosa.
empleado: un objeto con los datos actualizados del empleado.
error: un mensaje de error si hubo algún problema durante la actualización.
success: false si hubo un error en la actualización.
error: un mensaje de error si hubo algún problema durante la actualización.
Es importante controlar las respuestas del servidor para que JS pueda actuar en consecuencia. En este caso, si la actualización fue exitosa, se actualizará la fila correspondiente en la tabla de empleados.
4. Actualizar la fila en la tabla
Una vez que el servidor haya respondido con los datos actualizados, debemos actualizar la fila correspondiente en la tabla de empleados.
// Función para actualizar la fila de la tabla con los nuevos datosfunctionactualizarFila(empleado){// Encontrar la fila correspondiente en la tablaconstfila=document.querySelector(`tr[data-id='${empleado.emp_no}']`);console.log(fila);if(fila){fila.children[1].textContent=empleado.first_name;// Nombrefila.children[2].textContent=empleado.last_name;// Apellidofila.children[3].textContent=empleado.birth_date;// Fecha de nacimientofila.children[4].textContent=empleado.hire_date;// Fecha de contrataciónfila.children[5].textContent=empleado.gender;// Género}fila.style.display='none';// Ocultar la fila para forzar el re-renderizadofila.style.display='';// Volver a mostrar la fila con los datos actualizados}
En esta función el único cambio que hemos realizado es añadir el data-id a las filas de la tabla. De esta manera, podemos identificar la fila que queremos actualizar. Ahora dedemos actualizar nuestra código php que genera la tabla de empleados para que incluya el data-id en cada fila.
De esta manera, cada fila tendrá un atributo data-id que contiene el ID del empleado. Esto nos permitirá identificar la fila correcta para actualizarla con los nuevos datos.
Explicación de los pasos realizados:
Formulario Modal: El formulario de edición permanece intacto, con validaciones de HTML5. Al hacer clic en "Guardar", el formulario se envía de manera asíncrona sin recargar la página.
AJAX: Utilizamos JavaScript con AJAX para enviar los datos al servidor sin recargar la página. Cuando el servidor responde con los datos actualizados, se utiliza el DOM para actualizar la fila de la tabla correspondiente.
PHP: El archivo editarEmpleado.php recibe los datos del formulario, realiza las validaciones y ejecuta la consulta UPDATE para actualizar los datos del empleado en la base de datos.
Actualización en la tabla: Al recibir la respuesta del servidor, la fila correspondiente en la tabla de empleados se actualiza automáticamente con los nuevos datos.
Resumen
En este punto, hemos implementado un sistema para editar empleados sin salir de la página. Usamos AJAX para enviar los datos de forma asíncrona, actualizamos la fila de la tabla de empleados utilizando el DOM, y validamos las fechas en el servidor para asegurar que los datos sean correctos.
3.7.6 Eliminar empleados (con validación)
Objetivo: Eliminar un empleado de la base de datos, pero con ciertas restricciones. La eliminación de un empleado implica primero validar si el empleado está relacionado con la tabla de departamentos. Si está relacionado, cerraremos sus periodos (cerrando registros activos), pero no eliminaremos el empleado de la base de datos. Si no está relacionado con ningun departamento, el empleado podrá ser eliminado físicamente.
Flujo de validación:
Comprobar si el empleado es jefe de departamento:
Verificamos si el emp_no del empleado está relacionado con algún departamento como jefe. Si es así, no se puede eliminar.
Cerrar periodos activos:
Si el empleado tiene relación con algún departamento, cerramos estos registros con una fecha anterior a la actual en (departamentos, salarios, títulos).
Eliminar el empleado solo si no tiene relaciones activas:
Si el empleado no tiene relaciones con departamentos, lo eliminamos físicamente de la base de datos.
Pasos a seguir:
Comprobar si el empleado tiene relaciones activas (jefe de departamento, salarios, títulos).
Cerrar periodos: Si el empleado está relacionado, cerramos sus registros.
Eliminar al empleado si no tiene relaciones.
1. Modificación en la función eliminarEmpleado() con validaciones
La función de eliminación ahora debe validar si el empleado puede ser eliminado y cerrar los periodos correspondientes en lugar de eliminarlo físicamente si está relacionado con algún departamento, salario o título.
// Función para eliminar un empleado con validacionesfunctioneliminarEmpleado(emp_id){// Mostrar confirmación al usuarioconstconfirmacion=confirm("¿Estás seguro de que deseas eliminar este empleado?");if(confirmacion){// Enviar solicitud AJAX para verificar si el empleado puede ser eliminadofetch('eliminarEmpleado.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({emp_id:emp_id})// Enviar el ID del empleado}).then(response=>response.json()).then(data=>{if(data.success){if(data.action==="cerrar_periodos"){// Si se cierra el periodo, mostrar mensaje informando de la acciónalert("El empleado ha sido desactivado y sus periodos han sido cerrados.");}else{// Si se puede eliminar físicamente, eliminar la fila de la tablaeliminarFila(emp_id);alert("Empleado eliminado correctamente.");}}else{alert(data.error||"Error al eliminar el empleado.");}}).catch(error=>{console.error('Error:',error);alert('Error en la eliminación.');});}}
La función anterior hace referencia a la función eliminarFila(emp_id) que elimina la fila de la tabla de empleados. Esta función se ejecutará solo si el empleado se elimina físicamente de la base de datos. Debemos añadir esta función en nuestro fichero javascript para eliminar la fila de la tabla.
Función JavaScript para eliminar la fila de la tabla
// Función para eliminar la fila de la tabla después de la eliminaciónfunctioneliminarFila(emp_id){// Encontrar la fila correspondiente en la tabla usando el data-idconstfila=document.querySelector(`tr[data-id='${emp_id}']`);if(fila){// Eliminar la fila de la tablafila.remove();}}
2. Creación del escript PHP
El archivo PHP eliminarEmpleado.php ahora debe verificar si el empleado está relacionado con algún departamento, salario o título. Si el empleado es jefe de un departamento, no podrá ser eliminado. Si está relacionado con periodos abiertos, los cerraremos con una fecha anterior a la actual.
Código PHP para validación y eliminación:
script PHP para validar la eliminación del empleado
<?phptry{// Conexión a la base de datos con MySQLi orientado a objetos$conexion=newmysqli("localhost","root","","employees");// Verificar si la conexión fue exitosaif($conexion->connect_error){thrownewException("Error en la conexión: ".$conexion->connect_error);}// Recibir los datos JSON enviados por AJAX$data=json_decode(file_get_contents("php://input"));if($data){$emp_id=$data->emp_id;$fecha_actual=newDateTime();$fecha_actual_str=$fecha_actual->format('Y-m-d');// **Validación 1: Comprobar si el empleado es jefe de un departamento activo**$query_departamento="SELECT COUNT(*) FROM departments WHERE dept_mgr = ? AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_departamento);$stmt->bind_param("i",$emp_id);// Enlazamos el parámetro (emp_id)$stmt->execute();$stmt->bind_result($jefe_departamento);$stmt->fetch();$stmt->close();if($jefe_departamento>0){// Si el empleado es jefe de un departamento, no lo eliminamosechojson_encode(['success'=>false,'error'=>'El empleado es jefe de un departamento y no se puede eliminar.']);exit;}// **Validación 2: Verificar si el empleado está en algún departamento (tiene registros activos)**$query_departamentos="SELECT COUNT(*) FROM dept_emp WHERE emp_no = ? AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_departamentos);$stmt->bind_param("i",$emp_id);// Enlazamos el parámetro (emp_id)$stmt->execute();$stmt->bind_result($tiene_departamento);$stmt->fetch();$stmt->close();if($tiene_departamento>0){// Si el empleado está en un departamento, cerramos sus periodos en departamentos, salarios y títulos// Cerrar registros de departamento activos$query_departamentos_update="UPDATE dept_emp SET to_date = ? WHERE emp_no = ? AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_departamentos_update);$stmt->bind_param("si",$fecha_actual_str,$emp_id);// Enlazamos los parámetros$stmt->execute();$stmt->close();// Cerrar registros de salario activos$query_salarios_update="UPDATE salaries SET to_date = ? WHERE emp_no = ? AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_salarios_update);$stmt->bind_param("si",$fecha_actual_str,$emp_id);// Enlazamos los parámetros$stmt->execute();$stmt->close();// Cerrar registros de título activos$query_titulos_update="UPDATE titles SET to_date = ? WHERE emp_no = ? AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_titulos_update);$stmt->bind_param("si",$fecha_actual_str,$emp_id);// Enlazamos los parámetros$stmt->execute();$stmt->close();echojson_encode(['success'=>true,'action'=>'cerrar_periodos']);}else{// **Validación 3: Si no está en ningún departamento (ni salarios, ni títulos), eliminamos el empleado**$query_eliminar="DELETE FROM employees WHERE emp_no = ?";$stmt=$conexion->prepare($query_eliminar);$stmt->bind_param("i",$emp_id);// Enlazamos el parámetro (emp_id)$stmt->execute();$stmt->close();echojson_encode(['success'=>true,'action'=>'eliminar']);}}else{echojson_encode(['success'=>false,'error'=>'ID del empleado no válido.']);}}catch(Exception$e){echojson_encode(['success'=>false,'error'=>$e->getMessage()]);}$conexion->close();?>
<?phptry{// Conexión a la base de datos con PDO$conexion=newPDO("mysql:host=localhost;dbname=employees","root","");$conexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);// Recibir los datos JSON enviados por AJAX$data=json_decode(file_get_contents("php://input"));if($data){$emp_id=$data->emp_id;$fecha_actual=newDateTime();$fecha_actual_str=$fecha_actual->format('Y-m-d');// **Validación 1: Comprobar si el empleado es jefe de un departamento activo**$query_departamento="SELECT COUNT(*) FROM departments WHERE dept_mgr = :emp_id AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_departamento);$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);$stmt->execute();$jefe_departamento=$stmt->fetchColumn();if($jefe_departamento>0){// Si el empleado es jefe de un departamento, no lo eliminamosechojson_encode(['success'=>false,'error'=>'El empleado es jefe de un departamento y no se puede eliminar.']);exit;}// **Validación 2: Verificar si el empleado está en algún departamento (tiene registros activos)**$query_departamentos="SELECT COUNT(*) FROM dept_emp WHERE emp_no = :emp_id AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_departamentos);$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);$stmt->execute();$tiene_departamento=$stmt->fetchColumn();if($tiene_departamento>0){// Si el empleado está en un departamento, cerramos sus periodos en departamentos, salarios y títulos// Cerrar registros de departamento activos$query_departamentos_update="UPDATE dept_emp SET to_date = :fecha_actual WHERE emp_no = :emp_id AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_departamentos_update);$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);$stmt->bindParam(':fecha_actual',$fecha_actual_str,PDO::PARAM_STR);$stmt->execute();// Cerrar registros de salario activos$query_salarios_update="UPDATE salaries SET to_date = :fecha_actual WHERE emp_no = :emp_id AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_salarios_update);$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);$stmt->bindParam(':fecha_actual',$fecha_actual_str,PDO::PARAM_STR);$stmt->execute();// Cerrar registros de título activos$query_titulos_update="UPDATE titles SET to_date = :fecha_actual WHERE emp_no = :emp_id AND to_date = '9999-01-01'";$stmt=$conexion->prepare($query_titulos_update);$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);$stmt->bindParam(':fecha_actual',$fecha_actual_str,PDO::PARAM_STR);$stmt->execute();echojson_encode(['success'=>true,'action'=>'cerrar_periodos']);}else{// **Validación 3: Si no está en ningún departamento (ni salarios, ni títulos), eliminamos el empleado**$query_eliminar="DELETE FROM employees WHERE emp_no = :emp_id";$stmt=$conexion->prepare($query_eliminar);$stmt->bindParam(':emp_id',$emp_id,PDO::PARAM_INT);$stmt->execute();echojson_encode(['success'=>true,'action'=>'eliminar']);}}else{echojson_encode(['success'=>false,'error'=>'ID del empleado no válido.']);}}catch(PDOException$e){echojson_encode(['success'=>false,'error'=>$e->getMessage()]);}$conexion=null;?>
Este script PHP se encarga de recibir el ID del empleado a eliminar, verificar si el empleado es jefe de un departamento, y si no lo es, proceder a cerrar los periodos activos o eliminarlo físicamente de la base de datos. Las respuestas pueden ser:
success: true si la acción fue exitosa.
action: cerrar_periodos si se cerraron los periodos activos.
action: eliminar si el empleado fue eliminado físicamente.
error: un mensaje de error si hubo algún problema durante la operación.
3. Explicación de los pasos en PHP:
Comprobación si el empleado es jefe de un departamento: Si el empleado tiene el emp_no en la columna dept_mgr de la tabla departments, no puede ser eliminado.
Cierre de periodos activos: Si el empleado tiene registros activos en salarios, títulos o departamentos, se actualizan sus registros con una fecha anterior a la actual (to_date se actualiza).
Eliminación física: Si el empleado no tiene relaciones activas, se elimina físicamente de la base de datos.
Devolución del estado: El servidor responde con success: true y la acción realizada (cerrar periodos o eliminar).
Resumen del flujo de eliminación de empleados:
Comprobamos si el empleado es jefe de departamento.
Si está relacionado con departamentos, salarios o títulos, cerramos esos registros con una fecha anterior a la actual.
Eliminamos físicamente al empleado solo si no tiene relaciones activas.
3.7.7 Alta de empleados
Objetivos:
Generar un nuevo ID automáticamente para los empleados cuando se agreguen.
Fecha de alta por defecto: La fecha de alta debe ser la del día en que el empleado se agrega.
Campos a rellenar por el usuario: Nombre, Apellido, Fecha de nacimiento, Fecha de contratación y Género.
Validaciones tanto en JavaScript como en PHP para asegurar que los datos ingresados son correctos.
Pasos a seguir:
Crear el formulario de alta en la páginaemployees.php.
Enviar el formulario con AJAX para agregar el empleado a la base de datos.
Validar los datos en JavaScript antes de enviarlos al servidor.
Procesar la inserción en el servidor con PHP, asignando un ID automático y la fecha de alta actual.
Mostrar el nuevo empleado en la tabla sin recargar la página.
1. Crear el formulario de alta de empleados en employees.php:
En la página donde muestras la lista de empleados, vamos a utilizar el mismo modal que utilizamos para editar empleados, pero ahora lo usaremos para agregar nuevos empleados.
2. Función JavaScript para manejar la inserción:
Vamos a enviar los datos del formulario a través de AJAX para agregar al empleado sin recargar la página.
Función JavaScript para enviar los datos de alta del empleado:
Vamos a necesitar dos funciones, una para abrir el formulario y otra para guardar el empleado. La función guardarEmpleado() se encargará de enviar los datos al servidor y agregar el nuevo empleado a la tabla, y recoger los errores en caso de que los haya. Por otro lado, hay que añadir la función agregarEmpleadoATabla() que se encargará de agregar el nuevo empleado a la tabla de empleados. Por defecto, lo añadiremos como primer elemento de la tabla.
// Función para guardar el empleadofunctionguardarEmpleado(){constnombre=document.getElementById('nombre').value;constapellido=document.getElementById('apellido').value;constfecha_nacimiento=document.getElementById('fecha_nacimiento').value;constfecha_contratacion=document.getElementById('fecha_contratacion').value;constgenero=document.getElementById('genero').value;// Validaciones en JavaScriptif(!nombre||!apellido||!fecha_nacimiento||!fecha_contratacion||!genero){alert("Todos los campos son obligatorios.");return;}// Validación de fechas: Fecha de nacimiento debe ser 18 años antes que la fecha de contrataciónconstfechaNacimiento=newDate(fecha_nacimiento);constfechaContratacion=newDate(fecha_contratacion);constedadMinima=newDate();edadMinima.setFullYear(edadMinima.getFullYear()-18);if(fechaNacimiento>edadMinima){alert("La fecha de nacimiento debe ser al menos 18 años antes que la fecha de contratación.");return;}if(fechaContratacion>newDate()){alert("La fecha de contratación no puede ser mayor a la fecha actual.");return;}// Enviar los datos al servidor usando AJAX (fetch)fetch('agregarEmpleado.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({'nombre':nombre,'apellido':apellido,'fecha_nacimiento':fecha_nacimiento,'fecha_contratacion':fecha_contratacion,'genero':genero})}).then(response=>response.json()).then(data=>{if(data.success){// Si la inserción fue exitosa, agregar la fila en la tabla sin recargar la páginaagregarEmpleadoATabla(data.empleado);cerrarFormulario();}else{alert("Error al agregar el empleado.");}}).catch(error=>{console.error('Error:',error);alert("Error al agregar el empleado.");});}// Función para agregar el empleado a la tablafunctionagregarEmpleadoATabla(empleado){consttabla=document.getElementById('empleadosTable');// insertar la nueva fila al principio de la tablaconstnuevaFila=tabla.insertRow(0);nuevaFila.setAttribute('data-id',empleado.emp_no);nuevaFila.innerHTML=` <td>${empleado.emp_no}</td> <td>${empleado.first_name}</td> <td>${empleado.last_name}</td> <td>${empleado.birth_date}</td> <td>${empleado.hire_date}</td> <td>${empleado.gender}</td> <td><button onclick="editarEmpleado(${empleado.emp_no})">Editar</button></td> <td><button onclick="eliminarEmpleado(${empleado.emp_no})">Eliminar</button></td> `;}
3. PHP para procesar el alta de empleados (agregarEmpleado.php):
En el servidor, creamos el archivo agregarEmpleado.php para procesar el alta del empleado. Asignamos un ID automático y la fecha de alta actual.
Código PHP para agregar un empleado:
En este archivo, recibimos los datos del formulario enviados por AJAX y los insertamos en la base de datos. Recibiremos un objeto JSON conlos datos del empleado, por ejemplo:
Nuestro código PHP se encargará de procesar este JSON y agregar el empleado a la base de datos. Crearemos un fichero llamado agregarEmpleado.php que se encargará de recibir los datos del formulario y agregarlos a la base de datos.
Como ves en el ejemplo anterior, falta el campo emp_id porque no lo enviamos desde el formulario. En el código PHP, calcularemos el siguiente ID automáticamente, será un número más que el máximo ID existente en la tabla de empleados. De esta manera es tranasprente para el usuario y no tiene que preocuparse por el ID.
<?php// Conexión a la base de datos con MySQLi OO$host=getenv('MYSQL_HOST');$user=getenv('MYSQL_USER');$pass=getenv('MYSQL_PASSWORD');$db='employees';$conexion=newmysqli($host,$user,$pass,$db);// Verificar conexiónif($conexion->connect_error){echojson_encode(['success'=>false,'error'=>"Conexión fallida: ".$conexion->connect_error]);exit;}// Recibir los datos JSON enviados por AJAX$data=json_decode(file_get_contents("php://input"));if($data){/* Extraer datos del JSON */$nombre=$data->nombre;$apellido=$data->apellido;$fecha_nacimiento=$data->fecha_nacimiento;$fecha_contratacion=$data->fecha_contratacion;// Usamos la fecha de contratación como fecha de alta$genero=$data->genero;// Convertir las fechas a formato string (Y-m-d)$fecha_nacimiento_str=date('Y-m-d',strtotime($fecha_nacimiento));// Convertir la fecha de nacimiento$fecha_contratacion_str=date('Y-m-d',strtotime($fecha_contratacion));// Convertir la fecha de contratación// Calcular el siguiente ID del empleado (MAX(emp_no) + 1)$query_max_id="SELECT MAX(emp_no) FROM employees";$stmt=$conexion->prepare($query_max_id);$stmt->execute();$max_id=$stmt->fetchColumn();// Si no hay empleados (es el primer registro), establecer el emp_no como 1$nuevo_id=$max_id?$max_id+1:1;// Insertar el nuevo empleado en la base de datos$query="INSERT INTO employees (emp_no, first_name, last_name, birth_date, hire_date, gender) VALUES (?, ?, ?, ?, ?, ?)";$stmt=$conexion->prepare($query);if(!$stmt){echojson_encode(['success'=>false,'error'=>"Error en la preparación de la consulta: ".$conexion->error]);exit;}$stmt->bind_param("isssss",$nuevo_id,$nombre,$apellido,$fecha_nacimiento_str,$fecha_contratacion_str,$genero);$stmt->execute();/* Devolver el nuevo empleado con su ID generado */$empleado={'emp_no'=>$nuevo_id,// Pasamos el ID calculado'first_name'=>$nombre,'last_name'=>$apellido,'birth_date'=>$fecha_nacimiento_str,'hire_date'=>$fecha_contratacion_str,'gender'=>$genero}echojson_encode(['success'=>true,'empleado'=>$empleado]);$stmt->close();$conexion->close();}else{echojson_encode(['success'=>false,'error'=>'Datos inválidos.']);exit;}
<?phptry{// Conexión a la base de datos con PDO$conexion=newPDO("mysql:host=localhost;dbname=employees","root","");$conexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);// Recibir los datos JSON enviados por AJAX$data=json_decode(file_get_contents("php://input"));if($data){// Extraer datos del JSON$nombre=$data->nombre;$apellido=$data->apellido;$fecha_nacimiento=$data->fecha_nacimiento;$fecha_contratacion=$data->fecha_contratacion;// Usamos la fecha de contratación como fecha de alta$genero=$data->genero;// Convertir las fechas a formato string (Y-m-d)$fecha_nacimiento_str=date('Y-m-d',strtotime($fecha_nacimiento));// Convertir la fecha de nacimiento$fecha_contratacion_str=date('Y-m-d',strtotime($fecha_contratacion));// Convertir la fecha de contratación// **Calcular el siguiente ID del empleado** (MAX(emp_no) + 1)$query_max_id="SELECT MAX(emp_no) FROM employees";$stmt=$conexion->prepare($query_max_id);$stmt->execute();$max_id=$stmt->fetchColumn();// Si no hay empleados (es el primer registro), establecer el emp_no como 1$nuevo_id=$max_id?$max_id+1:1;// Insertar el nuevo empleado en la base de datos$query="INSERT INTO employees (emp_no, first_name, last_name, birth_date, hire_date, gender) VALUES (:emp_no, :nombre, :apellido, :fecha_nacimiento, :fecha_contratacion, :genero)";$stmt=$conexion->prepare($query);$stmt->bindParam(':emp_no',$nuevo_id,PDO::PARAM_INT);// Usar el ID calculado$stmt->bindParam(':nombre',$nombre,PDO::PARAM_STR);$stmt->bindParam(':apellido',$apellido,PDO::PARAM_STR);$stmt->bindParam(':fecha_nacimiento',$fecha_nacimiento_str,PDO::PARAM_STR);$stmt->bindParam(':fecha_contratacion',$fecha_contratacion_str,PDO::PARAM_STR);// Usamos la fecha de contratación$stmt->bindParam(':genero',$genero,PDO::PARAM_STR);$stmt->execute();// Devolver el nuevo empleado con su ID generado$empleado=['emp_no'=>$nuevo_id,// Pasamos el ID calculado'first_name'=>$nombre,'last_name'=>$apellido,'birth_date'=>$fecha_nacimiento_str,'hire_date'=>$fecha_contratacion_str,'gender'=>$genero];echojson_encode(['success'=>true,'empleado'=>$empleado]);}else{echojson_encode(['success'=>false,'error'=>'Datos inválidos.']);}}catch(PDOException$e){echojson_encode(['success'=>false,'error'=>'Error en el servidor: '.$e->getMessage()]);}$conexion=null;?>
Resumen del flujo para agregar un empleado:
Formulario en HTML: El formulario de alta es mostrado en un modal.
Validación en JavaScript: Se valida la fecha de nacimiento y la fecha de contratación.
Envío de datos con AJAX: Los datos se envían al servidor mediante fetch como un JSON.
Inserción en la base de datos con PHP: El empleado es insertado en la base de datos con un ID automático.
Actualizar la tabla: El nuevo empleado es añadido a la tabla sin recargar la página usando DOM.