Hola y bienvenid@s a este tutorial en donde te enseñaré como crear una app de lista de tareas usando PHP y MySQL, usaremos una base de datos de MySQL para almacenar el texto de las tareas. Esta pequeña aplicación creada en PHP es una excelente forma de ver cómo podemos crear una simple pero intuitiva app de lista de tareas.
En esta aplicación de lista de tareas, los usuarios pueden agregar o eliminar fácilmente sus tareas. Las tareas que el usuario ha agregado a esta aplicación se almacenarán en base de datos MySQL, por lo que no se eliminarán al actualizar o cerrar el navegador web, todo esto se hará utilizando las siguientes tecnologías:
- PHP
- MySQL
- CSS
- JavaScript
- Jquery
Nota importante: Para poder seguir este tutorial, debes tener instalado en tu computadora servidor web local como XAMPP
Crea una aplicación de lista de tareas con PHP y MySQL [Código fuente]
Para crear esta aplicación de lista de tareas con PHP, primero debemos crear un archivo llamado index.html. Después de crear dicho archivo, simplemente copia y pega el código mostrado a continuación.
Archivo index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<!DOCTYPE html> <html lang="es" dir="ltr"> <head> <meta charset="utf-8"> <title>Lista de tareas con PHP y MySQL</title> <link rel="stylesheet" href="style.css"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Iconscout Link For Icons --> <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css"> <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script> </head> <body> <form name="guardar_tarea" id="guardar_tarea"> <div class="wrapper"> <div class="task-input"> <img src="bars-icon.svg" alt="icon"> <input type="text" name="tarea" id="tarea" placeholder="Agregar nueva tarea" required> <input type="hidden" name="id_tarea" id="id_tarea" value="0"> </div> <div class="controls"> <div class="filters"> <span class="active" id="all" onclick="cargar_tareas('null')">Todas</span> <span id="pending" onclick="cargar_tareas('0')">Pendientes</span> <span id="completed" onclick="cargar_tareas('1')">Completadas</span> </div> <button type="button" class="clear-btn active" onclick="eliminar_todo();" >Borrar todo</button> </div> <div id="loader"></div> <ul class="task-box"></ul> </div> </form> <script src="app.js" async></script> </body> </html> |
El segundo archivo que vamos a crear lo vamos a nombrar style.css, este archivo se encarga de darle una mejora visual a nuestra aplicación de lista de tareas.
Archivo style.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
/* Import Google Font - Poppins */ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap'); *{ margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } body{ width: 100%; height: 100vh; overflow: hidden; background: linear-gradient(270deg,#0652DD, #3c87ff); } ::selection{ color: #fff; background: #3C87FF; } .wrapper{ max-width: 450px; padding: 28px 0 30px; margin: 137px auto; background: #fff; border-radius: 7px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); } .task-input{ height: 52px; padding: 0 25px; position: relative; } .task-input img{ top: 50%; position: absolute; transform: translate(17px, -50%); } .task-input input{ height: 100%; width: 100%; outline: none; font-size: 18px; border-radius: 5px; padding: 0 20px 0 53px; border: 1px solid #999; } .task-input input:focus, .task-input input.active{ padding-left: 52px; border: 2px solid #3C87FF; } .task-input input::placeholder{ color: #bfbfbf; } .controls, li{ display: flex; align-items: center; justify-content: space-between; } .controls{ padding: 15px 15px; border-bottom: 1px solid #ccc; } .filters span{ margin: 0 8px; font-size: 17px; color: #444444; cursor: pointer; } .filters span:first-child{ margin-left: 0; } .filters span.active{ color: #3C87FF; } .controls .clear-btn{ border: none; opacity: 0.6; outline: none; color: #fff; cursor: pointer; font-size: 13px; padding: 7px 13px; border-radius: 4px; letter-spacing: 0.3px; pointer-events: none; transition: transform 0.25s ease; background: linear-gradient(135deg, #1798fb 0%, #2D5CFE 100%); } .clear-btn.active{ opacity: 0.9; pointer-events: auto; } .clear-btn:active{ transform: scale(0.93); } .task-box{ margin-top: 20px; margin-right: 5px; padding: 0 20px 10px 25px; } .task-box.overflow{ overflow-y: auto; max-height: 300px; } .task-box::-webkit-scrollbar{ width: 5px; } .task-box::-webkit-scrollbar-track{ background: #f1f1f1; border-radius: 25px; } .task-box::-webkit-scrollbar-thumb{ background: #e6e6e6; border-radius: 25px; } .task-box .task{ list-style: none; font-size: 17px; margin-bottom: 18px; padding-bottom: 16px; align-items: flex-start; border-bottom: 1px solid #ccc; } .task-box .task:last-child{ margin-bottom: 0; border-bottom: 0; padding-bottom: 0; } .task-box .task label{ display: flex; align-items: flex-start; } .task label input{ margin-top: 7px; accent-color: #3C87FF; } .task label p{ user-select: none; margin-left: 12px; word-wrap: break-word; } .task label p.checked{ text-decoration: line-through; } .task-box .settings{ position: relative; } .settings :where(i, li){ cursor: pointer; } .settings .task-menu{ z-index: 10; right: -5px; bottom: -65px; padding: 5px 0; background: #fff; position: absolute; border-radius: 4px; transform: scale(0); transform-origin: top right; box-shadow: 0 0 6px rgba(0,0,0,0.15); transition: transform 0.2s ease; } .task-box .task:last-child .task-menu{ bottom: 0; transform-origin: bottom right; } .task-box .task:first-child .task-menu{ bottom: -65px; transform-origin: top right; } .task-menu.show{ transform: scale(1); } .task-menu li{ height: 25px; font-size: 16px; margin-bottom: 2px; padding: 17px 15px; cursor: pointer; justify-content: flex-start; } .task-menu li:last-child{ margin-bottom: 0; } .settings li:hover{ background: #f5f5f5; } .settings li i{ padding-right: 8px; } @media (max-width: 400px) { body{ padding: 0 10px; } .wrapper { padding: 20px 0; } .filters span{ margin: 0 5px; } .task-input{ padding: 0 20px; } .controls{ padding: 18px 20px; } .task-box{ margin-top: 20px; margin-right: 5px; padding: 0 15px 10px 20px; } .task label input{ margin-top: 4px; } } #loader{ text-align:center; font-size:13px; color:#999; } |
Ahora vamos a crear un archivo JavaScript, lo vamos a nombrar app.js. El archivo app.js se encargará de darle un poco de dinamismo a nuestra aplicación web a través de JavaScript, para la creación, lectura, actualización y eliminación de los datos, todo ello utilizando la tecnología AJAX jQuery.
Archivo app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
$('#tarea').focus(); function cargar_tareas(estado=null){ $.ajax({ url:'tareas_ajax.php?action=ajax&estado='+estado, beforeSend: function(objeto){ $('#loader').html('Cargando...'); }, success:function(data){ $(".task-box").html(data).fadeIn('slow'); $('#loader').html(''); } }) } cargar_tareas(); function eliminar_tarea(id) { if (confirm('Realmente deseas eliminar esta tarea?')){ $("#loader").fadeIn('slow'); $.ajax({ url:'tareas_ajax.php?action=ajax&delete='+id, beforeSend: function(objeto){ $('#loader').html('Cargando...'); }, success:function(data){ $(".task-box").html(data).fadeIn('slow'); $('#loader').html(''); } }) } } function actualizar_estado(id){ var txt_estado=0; if( $('#'+id).is(':checked') ){ txt_estado=1; } $.ajax({ url:'tareas_ajax.php?action=ajax&update='+id+'&txt_estado='+txt_estado, success:function(data){ $(".task-box").html(data).fadeIn('slow'); $('#loader').html(''); } }) } $( "#guardar_tarea" ).submit(function( event ) { var parametros = $(this).serialize(); $.ajax({ type: "get", url: "tareas_ajax.php?action=ajax", data: parametros, beforeSend: function(objeto){ $("#loader").html("Mensaje: Cargando..."); }, success: function(datos){ $(".task-box").html(datos); $('#loader').html(''); $("#tarea").val(''); $("#id_tarea").val(0); $("#tarea").focus(); } }); event.preventDefault(); }) function eliminar_todo(){ if(confirm('Realmente desea eliminar todas las tareas?')){ $("#loader").fadeIn('slow'); $.ajax({ url:'tareas_ajax.php?action=ajax&delete_all=all', beforeSend: function(objeto){ $('#loader').html('Cargando...'); }, success:function(data){ $(".task-box").html(data).fadeIn('slow'); $('#loader').html(''); } }) } } function editar_tarea(id,tarea){ $("#tarea").val(tarea); $("#id_tarea").val(id); $("#tarea").focus(); } function showMenu(selectedTask) { let menuDiv = selectedTask.parentElement.lastElementChild; menuDiv.classList.add("show"); document.addEventListener("click", e => { if(e.target.tagName != "I" || e.target != selectedTask) { menuDiv.classList.remove("show"); } }); } |
Como cuarto paso vamos a crear nuestra base de datos MySQL, esto para poder guardar nuestra lista de tareas en dicha base de datos. Para crear nuestra base de datos debemos abrir nuestro gestor de base de datos, en mi caso estoy usando phpMyAdmin, abrimos phpMyAdmin y creamos una base de datos llamada: test_app_task (para efectos de ejemplo la he nombrado así, pero tu puedes llamarla como desees), luego abrimos la base de datos recientemente creada y ejecutamos el siguiente código SQL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
CREATE TABLE `tareas` ( `id` int(11) NOT NULL, `tarea` varchar(100) NOT NULL, `estado` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- -- Índices para tablas volcadas -- -- -- Indices de la tabla `tareas` -- ALTER TABLE `tareas` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT de las tablas volcadas -- -- -- AUTO_INCREMENT de la tabla `tareas` -- ALTER TABLE `tareas` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; COMMIT; |
Ahora vamos a crear un archivo que nos servirá para conectarnos a la base de datos MySQL, lo llamaremos conexionDB.php
Archivo conexionDB.php
1 2 3 4 5 6 7 |
<?php # conectare la base de datos $host="localhost"; $user="root"; $pass=''; $db_name="test_app_task"; $link=mysqli_connect($host, $user, $pass, $db_name); |
Asegúrate de asignar los datos de conexión pertenecientes a tu servidor, si en el paso anterior de creación de la base de datos, nombraste de forma distinta la base de datos, entonces modifica la línea 5 y a la variable llamada $db_name asígnale el nombre de la base de datos que nombraste.
Ahora nos toca leer la información de la lista de tareas almacenadas en nuestra base de datos, para ello creamos el archivo tareas_ajax.php
Archivo tareas_ajax.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
<?php $action = (isset($_REQUEST['action'])&& $_REQUEST['action'] !=NULL)?$_REQUEST['action']:''; if($action == 'ajax'){ include("conexionDB.php"); $sWhere=""; if (isset($_REQUEST["estado"])){ $filtrar_estado=mysqli_real_escape_string($link,(strip_tags($_REQUEST["estado"],ENT_QUOTES))); if ($filtrar_estado!=null){ if ($filtrar_estado==0){ $sWhere=" where estado=0"; } else if ($filtrar_estado==1){ $sWhere=" where estado=1"; } } } $sTable = "tareas"; $sWhere .= " order by id desc"; if (isset($_REQUEST['delete'])){ $id_tarea=intval($_REQUEST['delete']); $delete=mysqli_query($link,"delete from $sTable where id='$id_tarea'"); } if (isset($_REQUEST['update'])){ $id_tarea=intval($_REQUEST['update']); $txt_estado=intval($_REQUEST['txt_estado']); $update=mysqli_query($link,"update $sTable set estado='$txt_estado' where id='$id_tarea'"); } if (isset($_REQUEST['tarea'])){ $id_tarea=intval($_REQUEST["id_tarea"]); $tarea=mysqli_real_escape_string($link,(strip_tags($_REQUEST["tarea"],ENT_QUOTES))); if ($id_tarea>0){ $sql="update tareas set tarea='$tarea' where id='$id_tarea'"; } else { $sql="INSERT INTO `tareas` (`id`, `tarea`, `estado`) VALUES (NULL, '$tarea', '0');"; } $insert = mysqli_query($link,$sql); } if (isset($_REQUEST['delete_all'])){ $delete=mysqli_query($link,"delete from $sTable "); } $sql="SELECT * FROM $sTable $sWhere "; $query = mysqli_query($link, $sql); $num=mysqli_num_rows($query); if ($num>0){ ?> <?php while($row=mysqli_fetch_array($query)){ $estado=$row['estado']; if ($estado==0){ $class=''; } else { $class='checked'; } ?> <li class="task"> <label for="${id}"> <input onclick="actualizar_estado(<?=$row['id']?>)" type="checkbox" id="<?=$row['id']?>" <?=$class;?>> <p class="<?=$class;?>"><?=$row['tarea']?></p> </label> <div class="settings"> <i onclick="showMenu(this)" class="uil uil-ellipsis-h"></i> <ul class="task-menu"> <li onclick="editar_tarea('<?=$row['id']?>','<?=$row['tarea']?>')"><i class="uil uil-pen"></i>Editar</li> <li onclick="eliminar_tarea('<?=$row['id']?>')"><i class="uil uil-trash"></i>Borrar</li> </ul> </div> </li> <?php } ?> <?php } } ?> |
Hemos finalizado con la creación de nuestra aplicación de lista de tareas con PHP y MySQL. Si haz seguido cada uno de los pasos detallados anteriormente puedes conseguir el resultado final como el de la demostración que se muestra a continuación.
Si tu código no funciona o haz tenido algún problema, tienes la opción de hacer una pequeña donación y descargar los archivos del código fuente usando el botón de descarga indicado a continuación .
Ver demostración Descargar archivos