Vamos ha realizar y explicar un CRUD, osea insertar, consultar, actualizar y borrar elementos de una tabla en MySQL, con PHP y la librería jQuery para las peticiones asíncronas con el servidor. Aunque hay varios tutoriales en internet, este artículo es una actualización a muchos escritos en nuestro blog que tiene código ya desfasado. Además no está de más aprender técnicas distintas de programación, aquí muestro las mías.

Descargar el ejemplo

Objetivo

Mostrar un listado de un tabla de datos, empleados, que tengamos la opción de agregar uno nuevo, editarlo y eliminarlo. Además completaremos el trabajo usando un plugin para jQuery para paginar y filtrar los resultados Datatables.

Base de datos

CREATE TABLE `crud_employees` (
  `id` mediumint(9) NOT NULL,
  `names` varchar(150) NOT NULL,
  `address` varchar(200) NOT NULL,
  `date_register` date NOT NULL,
  `phone` varchar(12) NOT NULL,
  `comment` tinytext NOT NULL,
  `salary` decimal(10,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `crud_employees`
  ADD PRIMARY KEY (`id`);
INSERT INTO `crud_employees` (`id`, `names`, `address`, `date_register`, `phone`, `comment`, `salary`) VALUES
(7, 'Jhon Williams', 'Calle Saint Seiya 239 Urb. Zodiaco', '2019-11-15', '+51 95418188', 'Compositor de grandes películas', '1200.50'),
(8, 'Anakin Skywalker', 'Calle Iron man #479 Urb. Vengadores', '2019-11-01', '+54 96385214', '', '1300.50'),
(9, 'Goku Sayayin', 'Calle Spiderman #678', '2019-11-15', '+61 98745632', '', '1400.60'),
(10, 'Tsubasa Olive Atom', 'Avenida Planeta de los Simios #998', '2019-11-18', '+84 96358742', 'Un buen juador de futbol', '1300.60'),
(11, 'Jhon Wick', 'Jiron Matones #785', '2019-11-07', '+1 852963250', 'Un gran profesional', '1800.00');

Aplicación web

database.class.php, esta clase nos permite conectarnos a la base de datos y realizar las operaciones importantes como insertar, actualizar y ejecutar alguna otra consulta.

<?php
class DataBase{
	private $BaseDatos = 'db_emocion';
	private $Servidor = 'localhost';
	private $Usuario = 'root';
	private $Clave = '';
	function Conexion() {
		$mysqli = new mysqli($this->Servidor, $this->Usuario, $this->Clave, $this->BaseDatos);
		$mysqli->set_charset("utf8");
		if ($mysqli->connect_error) {
	    die('Error de Conexión (' . $mysqli->connect_errno . ') '
				. $mysqli->connect_error);
		}else{
			return $mysqli;
			$mysqli -> mysqli_close();
		}
	}
	function Execute($q){
		$conexion = $this->Conexion();
		return $conexion->query($q);
	}
	function Insert($table, $data){ // con array - key - value
		$conexion = $this->Conexion();
		// Columnas
		$columns = "(";
		$coma = "";
		foreach ($data as $key => $value) {
			$columns .= $coma."`".$key."`";
			$coma = ",";
		}
		$columns .= ")";
		//valores
		$values = "(";
		$coma = "";
		foreach ($data as $key => $value) {
			$values .= $coma."'".$value."'";
			$coma = " ,";
		}
		$values .= ")";
		$sentence = "INSERT INTO $table $columns VALUES $values";
		if($conexion->query($sentence)){
			$resultArray = array('result' => true, 'insert_id' => $conexion->insert_id );
		}else{
			$resultArray = array('result' => false, 'error' => $conexion->connect_errno.":".$conexion->error );
		}
		return $resultArray;
	}
	function Update($table, $data, $condition){ // con array - key - value
		$conexion = $this->Conexion();
		// Cols to edit
		$coma = "";
		$cols_and_vals = "";
		foreach ($data as $key => $value) {
			$cols_and_vals .= $coma."`".$key."` = '".$value."'";
			$coma = ", ";
		}
		// Where condition
		$and = "";
		$condition_cols_vals = "";
		foreach ($condition as $key => $value) {
			$condition_cols_vals .= $and."`".$key."` = '".$value."'";
			$and = " AND ";
		}
		$sentence = "UPDATE $table SET $cols_and_vals WHERE $condition_cols_vals";
		if($conexion->query($sentence)){
			$resultArray = array('result' => true, 'affected_rows' => $conexion->affected_rows );
		}else{
			$resultArray = array('result' => false, 'error' => $conexion->connect_errno.":".$conexion->error );
		}
		return $resultArray;
	}
	function Search($data_to_search, $table, $columns, $condition_add=""){
		// Busqueda avanzada
		$conexion = $this->Conexion();
		$cols_vals = "";
		$coma = "";
		foreach ($columns as $key) {
			$cols_vals .= $coma.$key;
			$coma = ", ";
		}
		$q = "SELECT * FROM $table WHERE MATCH ( $cols_vals ) AGAINST ( '$data_to_search' IN NATURAL LANGUAGE MODE) ".$condition_add;
		return $conexion->query($q);
	}
}
$objDataBase = new DataBase;
?>

index.php, el archivo principal de nuestra aplicación, incluimos los archivos CSS, jQuery, además del plugin datatables. Irá un botón para llamar al formulario para añadir un nuevo empleado y contiene los encabezados de la tabla de resultados. A nivel de PHP incluimos, o llamamos, al archivo employee.list.php, que contiene la lista de empleados. Además hay un div llamado modalFrmEmployee, donde se mostrará el formulario para agregar nuevo empleado.

<html>
  <head>
    <title>CRUD PHP, MySQL, jQuery</title>
    <script src="jquery-3.4.1.min.js"></script>
    <link rel="stylesheet" href="styles.css">
    <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css"/>
  	<script type="text/javascript" src="//cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
  </head>
  <body>
    <div class="bg"></div>
    <div class="block">
      <a class="button showForm" href="#">Nuevo empleado</a>
      <table id="table" class="tables">
        <thead>
          <tr>
            <th>Nombres</th>
            <th>Direccion</th>
            <th>Fecha registro</th>
            <th>Telefono</th>
            <th>Salario</th>
            <th>Comentario</th>
            <th>Acciones</th>
          </tr>
        </thead>
        <tbody class="listEmployees">
          <?php include_once 'employee.list.php' ?>
        </tbody>
      </table>
    </div>
    <div class="modalFrmEmployee"></div>
  </body>
  <script src="funcs.js"></script>
</html>

funcs.js, aqui definimos las funciones o procedimientos haciendo uso de jQuery. En los comentario explicamos brevemente. Y si analizas el código te darás cuenta que no es complicado de entender.

// Añadir plugin a la tabla elegida
// En este caso enlazado con la tabla con id #table
$('#table').DataTable({
  "language": {
    "url": "//cdn.datatables.net/plug-ins/1.10.20/i18n/Spanish.json"
  }
});
// Listado de empleados
// Mediante AJAX llama la lista de empleados
function listEmployees(){
  event.preventDefault();
  $.ajax({
    method: "get",
    url: "employee.list.php"
  })
  .done(function( data ) {
    $(".listEmployees").html(data);
  });
}
// Mediante AJAX muestra el formulario Editar empleado
function showFormEmployee(id){
  $.ajax({
    method: "get",
    url: "employee.newedit.php?id="+id
  })
  .done(function( data ) {
    $(".modalFrmEmployee").html(data);
  });
  $(".bg, .modalFrmEmployee").show();
}
// Llama a la funcion de mostrar el formulario Editar empleado Nuevo
$(".showForm").click(function(event){
  event.preventDefault();
  showFormEmployee(0);
});
// Cerrar formulario Editar empleado
$(".modalFrmEmployee").on("click", ".hideForm", function(event){
  event.preventDefault();
  $(".bg, .modalFrmEmployee").hide();
});
// Grabar datos del formulario Empleado
$(document).on("submit","#frmEmployee",function(event){
  event.preventDefault();
  $.ajax({
    method: "post",
    url: "employee.save.php",
    data: $( this ).serialize()
  })
  .done(function( data ) {
    if(data.resultado){
      $(".bg, .modalFrmEmployee").hide();
      listEmployees();
    }
    alert(data.mensaje);
  });
});
// Llama a la funcion de mostrar el formulario Editar empleado
// para editar sus datos en base a su id
$(".listEmployees").on("click", ".edit", function(event){
  event.preventDefault();
  var employee_id = $(this).attr('data-id');
  showFormEmployee(employee_id);
});
// Eliminar empleado en base a su id
$(".listEmployees").on("click", ".delete", function(event){
  event.preventDefault();
  var delete_employee = confirm("¿Está seguro de eliminar?");
  if ( delete_employee ) {
    var employee_id = $(this).attr('data-id');
    $.ajax({
      method: "get",
      url: "employee.delete.php?id="+employee_id
    })
    .done(function( data ) {
      if(data.resultado){
        listEmployees();
      }
      alert(data.mensaje);
    });
  }
});

employee.list.php, el archivo muestra el listado de los empleados.

<?php
require_once 'dbconnect/database.class.php';
$objDB = new DataBase;
$result = $objDB->Execute('SELECT * FROM crud_employees');
while($employee = $result->fetch_assoc()){
  ?>
  <tr>
    <td><?= $employee['names'] ?></td>
    <td><?= $employee['address'] ?></td>
    <td><?= $employee['date_register'] ?></td>
    <td><?= $employee['phone'] ?></td>
    <td><?= $employee['salary'] ?></td>
    <td><?= $employee['comment'] ?></td>
    <td>
      <a class="edit" data-id="<?= $employee['id'] ?>" href="#">Editar</a>
      <a class="delete" data-id="<?= $employee['id'] ?>" href="#">Eliminar</a>
    </td>
  </tr>
  <?php
}
?>

employee.newedit.php, el archivo muestra el formulario para editar o agregar datos del nuevo empleado. Nos ahorramos código haciendo uso del mismo formulario tanto para agregar nuevo como para actualizar.

<?php
require_once 'dbconnect/database.class.php';
$objDB = new DataBase;
$id = $_GET['id'];
if($id>0){
  $result = $objDB->Execute("SELECT * FROM crud_employees WHERE id=$id");
  $employee = $result->fetch_assoc();
}
?>
  <form id="frmEmployee" class="form">
    <input type="hidden" name="id" value="<?= $id ?>" />
    <label>
      Nombres
      <input type="text" name="nombres" value="<?php if(isset($employee)) echo $employee['names'] ?>" required />
    </label>
    <label>
      Dirección
      <input type="text" name="direccion" value="<?php if(isset($employee)) echo $employee['address'] ?>" />
    </label>
    <label>
      Fecha registro
      <input type="date" name="fecha_registro" value="<?php if(isset($employee)) echo $employee['date_register'] ?>" />
    </label>
    <label>
      Teléfono
      <input type="tel" name="telefono" value="<?php if(isset($employee)) echo $employee['phone'] ?>" />
    </label>
    <label>
      Salario
      <input type="number" name="salario" value="<?php if(isset($employee)) echo $employee['salary'] ?>" step=".01" />
    </label>
    <label>
      Comentario
      <textarea name="comentario"><?php if(isset($employee)) echo $employee['comment'] ?></textarea>
    </label>
    <button class="button" type="submit">Guardar datos</button>
  </form>
  <a class="hideForm" href="#">Cerrar</a>

employee.save.php, guarda los datos del empleado recibidos del formulario. La respuesta que arroja esta en formato JSON, indicando si la operación fue exitosa o no, junto con un mensaje.

<?php
header('Content-type: application/json; charset=utf-8');
require_once 'dbconnect/database.class.php';
$objDB = new DataBase;
$id = $_POST['id'];
$employee_data = [
	'names' => $_POST['nombres'],
	'address' => $_POST['direccion'],
	'date_register' =>  $_POST['fecha_registro'],
	'phone' => $_POST['telefono'],
	'comment' => $_POST['comentario'],
	'salary' => $_POST['salario']
];
if($id==0){ // Nuevo
	$r = $objDB->Insert('crud_employees', $employee_data);
	if($r['result']){
		$arr = ['resultado' => true, 'mensaje' => 'Empleado añadido', 'id' => $r['insert_id'] ];
	}else{
		$arr = ['resultado' => false, 'mensaje' => $r['error']];
	}
}else{ // Update
	$r = $objDB->Update('crud_employees', $employee_data, ["id" => $id]);
	if($r['result']){
		$arr = ['resultado' => true, 'mensaje' => 'Empleado actualizado' ];
	}else{
		$arr = ['resultado' => false, 'mensaje' => $r['error']];
	}
}
die(json_encode($arr));

employee.delete.php, realiza la eliminación de un empleado, en base a su id. La respuesta que arroja está en formato JSON, indicando si la operación fue exitosa o no, junto con un mensaje.

<?php
header('Content-type: application/json; charset=utf-8');
require_once 'dbconnect/database.class.php';
$objDB = new DataBase;
$id = $_GET['id'];
$result = $objDB->Execute('DELETE FROM crud_employees WHERE id='.$id);
if($result){
	$arr = ['resultado' => true, 'mensaje' => 'Elemento eliminado' ];
}else{
	$arr = ['resultado' => false, 'mensaje' => $r['error']];
}
die(json_encode($arr));
?>

Para completar visualmente la aplicación podemos usar bootstrap, materialize o cualquier otro framework CSS de tu preferencia. Este es un CRUD básico, podemos luego añadir validaciones para evitar campos vacíos o temas de seguridad y evitar inyección sql.

Descargar el ejemplo