Ejercicio: Sistema de Diario Personal

Implementa un sistema completo de diario personal con PHP y MySQL

Intermediate Level ⏱️ 2-3 hours

Download Example Code

Learning Objectives

Database Connection

Learn to connect PHP to MySQL using MySQLi

Complete CRUD

Implement Create, Read, Update, Delete for records

File Manipulation

Dynamically generate PHP files

Search System

Implement search in content and metadata

Prerequisites

Conocimientos básicos de PHP
Conceptos básicos de MySQL
Entender HTML y CSS
Servidor local (XAMPP, WAMP, etc.)

Current Status of the Demo Entry

File: diario_ejercicio.php EXISTS

Size: 36636 bytes

Last modified: 2026-09-10 16:12:04

Current content:

<?php
// Incluir configuración
include_once '../database/config.php';

// Procesar el formulario - DEMO EDUCATIVA
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $opcion = $_POST['opcion'] ?? null;
    $mensaje = $_POST['mensaje'] ?? '';
    $nombre_archivo = $_POST['nombre_archivo'] ?? 'diario_ejercicio.php';

    switch ($opcion) {
        case 'crear':
            $contenido = "<?php\n// Mi Diario Personal - Entrada de ejemplo\n\$fecha = date('Y-m-d H:i:s');\n\$nombre = 'Usuario Demo';\n?>\n<html>\n<head>\n    <title><?php echo t('Ejercicio Diario de Programación'); ?> | ProgramandoWeb</title>\n</head>\n<body>\n    <h1>Mi Diario Personal</h1>\n    <p><strong>Fecha:</strong> <?php echo \$fecha; ?></p>\n    <p><strong>Nombre:</strong> <?php echo \$nombre; ?></p>\n    <div>\n        <h2>Mis pensamientos de hoy:</h2>\n        <p>Esta es una entrada de ejemplo en mi diario personal.</p>\n    </div>\n</body>\n</html>";
            file_put_contents($nombre_archivo, $contenido);
            $resultado = t("✅ Archivo de diario creado correctamente");
            break;

        case 'editar':
            $contenido_actual = file_exists($nombre_archivo) ? file_get_contents($nombre_archivo) : '';
            $nuevo_contenido = preg_replace('/<p>Esta es una entrada.*?<\/p>/', "<p>$mensaje</p>", $contenido_actual);
            file_put_contents($nombre_archivo, $nuevo_contenido);
            $resultado = t("✅ Entrada del diario actualizada");
            break;

        case 'eliminar':
            if (file_exists($nombre_archivo)) {
                unlink($nombre_archivo);
                $resultado = t("✅ Entrada del diario eliminada");
            } else {
                $resultado = t("⚠️ La entrada no existe");
            }
            break;

        case 'leer':
            if (file_exists($nombre_archivo)) {
                $contenido = file_get_contents($nombre_archivo);
                // Extraer solo el contenido visible
                preg_match('/<p>([^<]*)<\/p>/', $contenido, $matches);
                $resultado = $matches[1] ?? t("Contenido no encontrado");
            } else {
                $resultado = t("⚠️ La entrada no existe");
            }
            break;
    }
}

// Verificar estado actual del archivo de demo
$archivo_existe = file_exists('diario_ejercicio.php');
$contenido_actual = $archivo_existe ? file_get_contents('diario_ejercicio.php') : '';

$userInfo = getUserInfo();
?>
<!DOCTYPE html>
<html lang="<?php echo currentLang(); ?>">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="<?php echo t('Ejercicio práctico para crear un diario de programación. Pon en práctica tus habilidades de PHP, bases de datos y desarrollo web.'); ?>">
    <meta name="keywords" content="ejercicio PHP, practica PHP, proyecto PHP, diario ejercicio programación">
    <meta name="author" content="ProgramandoWeb - xlRaiko">
    <meta name="robots" content="index, follow">
    <link rel="canonical" href="https://programandoweb.site/ejemplos/diario_ejercicio">
    <meta property="og:type" content="article">
    <meta property="og:title" content="Ejercicio Diario de Programación | ProgramandoWeb">
    <meta property="og:description" content="Ejercicio práctico para crear un diario de programación. Pon en práctica tus habilidades de PHP, bases de datos y desarrollo web.">
    <meta property="og:url" content="https://programandoweb.site/ejemplos/diario_ejercicio">
    <meta property="og:image" content="https://programandoweb.site/assets/images/bannerProgramandoWeb.png">
    <meta property="og:site_name" content="ProgramandoWeb">
    <meta property="og:locale" content="<?php echo currentLang() === 'en' ? 'en_US' : 'es_ES'; ?>">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@programando_web">
    <meta name="twitter:title" content="Ejercicio Diario de Programación | ProgramandoWeb">
    <meta name="twitter:description" content="Ejercicio práctico para crear un diario de programación. Pon en práctica tus habilidades de PHP, bases de datos y desarrollo web.">
    <meta name="twitter:image" content="https://programandoweb.site/assets/images/bannerProgramandoWeb.png">
    <title><?php echo t('Ejercicio: Sistema de Diario Personal - Recursos de Programación'); ?></title>
    <link rel="stylesheet" href="../template/css/header.css">
    <link rel="stylesheet" href="../template/css/darktheme.css"> <!-- FOUC-FIX-DARKTHEME-CSS-LINK -->
    <link rel="stylesheet" href="template/css/diario_ejercicio.css">
    <link rel="icon" href="/favicon.ico">
</head>
<body>

    <header class="header">
        <div class="header-container">
            <a href="../" class="logo-link">
                <img src="../assets/images/logo.png" alt="Logo Programación" class="logo">
            </a>
        </div>
    </header>

    <?php include '../nav-bar.php'; ?>

    <main class="main-content" id="main-content">
        <div class="container">
            <article class="tutorial-article">
                <header class="article-header">
                    <h1 class="article-title">Ejercicio: Sistema de Diario Personal</h1>
                    <p class="article-subtitle">Implementa un sistema completo de diario personal con PHP y MySQL</p>
                    <div class="exercise-info">
                        <div class="difficulty">
                            <span class="badge intermediate"><?php echo t('Nivel Intermedio'); ?></span>
                            <span class="badge time-estimate">⏱️ 2-3 <?php echo t('horas'); ?></span>
                        </div>
                    </div>
                        </br>
                    <div>
                        <a href="descargas/Diario/diarioejercicio.zip" download="diarioejercicio.zip" class="download-btn">
                            <i class="fas fa-download"></i> <?php echo t('Descargar Código Ejemplo'); ?>
                        </a>
                    </div>
                </header>

                <!-- Objetivos del ejercicio -->
                <section class="content-section">
                    <h2><i class="fas fa-bullseye"></i> <?php echo t('Objetivos de Aprendizaje'); ?></h2>
                    
                    <div class="learning-objectives">
                        <div class="objective">
                            <i class="fas fa-database"></i>
                            <h3><?php echo t('Conexión a Base de Datos'); ?></h3>
                            <p><?php echo t('Aprender a conectar PHP con MySQL usando MySQLi'); ?></p>
                        </div>
                        <div class="objective">
                            <i class="fas fa-code"></i>
                            <h3><?php echo t('CRUD Completo'); ?></h3>
                            <p><?php echo t('Implementar Create, Read, Update, Delete de registros'); ?></p>
                        </div>
                        <div class="objective">
                            <i class="fas fa-file-code"></i>
                            <h3><?php echo t('Manipulación de Archivos'); ?></h3>
                            <p><?php echo t('Generar archivos PHP dinámicamente'); ?></p>
                        </div>
                        <div class="objective">
                            <i class="fas fa-search"></i>
                            <h3><?php echo t('Sistema de Búsqueda'); ?></h3>
                            <p><?php echo t('Implementar búsqueda en contenido y metadatos'); ?></p>
                        </div>
                    </div>
                </section>

                <!-- Requisitos previos -->
                <section class="content-section">
                    <h2><i class="fas fa-clipboard-check"></i> <?php echo t('Requisitos Previos'); ?></h2>
                    
                    <div class="prerequisites">
                        <div class="prerequisite-item">
                            <i class="fas fa-check-circle"></i>
                            <span><?php echo t('Conocimientos básicos de PHP'); ?></span>
                        </div>
                        <div class="prerequisite-item">
                            <i class="fas fa-check-circle"></i>
                            <span><?php echo t('Conceptos básicos de MySQL'); ?></span>
                        </div>
                        <div class="prerequisite-item">
                            <i class="fas fa-check-circle"></i>
                            <span><?php echo t('Entender HTML y CSS'); ?></span>
                        </div>
                        <div class="prerequisite-item">
                            <i class="fas fa-check-circle"></i>
                            <span><?php echo t('Servidor local (XAMPP, WAMP, etc.)'); ?></span>
                        </div>
                    </div>
                </section>

                <!-- Estado actual del archivo de demo -->
                <section class="content-section">
                    <h2><i class="fas fa-info-circle"></i> <?php echo t('Estado Actual de la Entrada de Demo'); ?></h2>
                    
                    <div class="estado-archivo">
                        <div class="archivo-info">
                            <p><strong><?php echo t('Archivo:'); ?></strong> 
                                <span class="badge <?php echo $archivo_existe ? 'existe' : 'no-existe'; ?>">
                                    <i class="fas <?php echo $archivo_existe ? 'fa-check-circle' : 'fa-times-circle'; ?>"></i>
                                    diario_ejercicio.php <?php echo $archivo_existe ? t('EXISTE') : t('NO EXISTE'); ?>
                                </span>
                            </p>
                            
                            <?php if ($archivo_existe): ?>
                                <p><strong><?php echo t('Tamaño:'); ?></strong> <?php echo filesize('diario_ejercicio.php'); ?> bytes</p>
                                <p><strong><?php echo t('Última modificación:'); ?></strong> <?php echo date('Y-m-d H:i:s', filemtime('diario_ejercicio.php')); ?></p>
                                
                                <?php if (!empty($contenido_actual)): ?>
                                    <p><strong><?php echo t('Contenido actual:'); ?></strong></p>
                                    <div class="contenido-archivo">
                                        <pre><?php echo htmlspecialchars($contenido_actual); ?></pre>
                                    </div>
                                <?php else: ?>
                                    <p><strong><?php echo t('Contenido actual:'); ?></strong> <em><?php echo t('El archivo está vacío'); ?></em></p>
                                <?php endif; ?>
                            <?php endif; ?>
                        </div>
                    </div>
                </section>

                <!-- Resultado de la última acción -->
                <?php if (isset($resultado)): ?>
                <section class="content-section">
                    <h2><i class="fas fa-bell"></i> <?php echo t('Resultado de la Última Acción'); ?></h2>
                    <div class="resultado-accion">
                        <div class="mensaje-resultado">
                            <i class="fas fa-info-circle"></i>
                            <?php echo $resultado; ?>
                        </div>
                    </div>
                </section>
                <?php endif; ?>

                <!-- Demo interactivo -->
                <section class="content-section">
                    <h2><i class="fas fa-play-circle"></i> <?php echo t('Prueba el Sistema de Diario'); ?></h2>
                    <p><?php echo t('Usa los siguientes controles para probar las funciones del diario personal en tiempo real:'); ?></p>
                    
                    <div class="live-example">
                        <div class="form-container">
                            <h3><?php echo t('Panel de Control del Diario'); ?></h3>
                            
                            <form method="POST" class="form-diario">
                                <?php echo csrf_field(); ?>
                    <?php echo honeypot_field(); ?>
                                <div class="botones-accion">
                                    <button type="submit" name="opcion" value="crear" class="btn btn-crear">
                                        <i class="fas fa-file"></i> <?php echo t('Crear Entrada'); ?>
                                    </button>
                                    
                                    <button type="submit" name="opcion" value="leer" class="btn btn-leer">
                                        <i class="fas fa-eye"></i> <?php echo t('Leer Entrada'); ?>
                                    </button>
                                    
                                    <button type="submit" name="opcion" value="eliminar" class="btn btn-eliminar">
                                        <i class="fas fa-trash"></i> <?php echo t('Eliminar Entrada'); ?>
                                    </button>
                                </div>

                                <div class="form-group">
                                    <label for="mensaje">
                                        <i class="fas fa-edit"></i> <?php echo t('Modificar contenido del diario:'); ?>
                                    </label>
                                    <textarea id="mensaje" name="mensaje" rows="4" 
                                              placeholder="<?php echo t('Escribe el nuevo contenido para tu entrada de diario...'); ?>"><?php echo t('Hoy fue un día increíble. Aprendí mucho sobre PHP y la manipulación de archivos.'); ?></textarea>
                                    <button type="submit" name="opcion" value="editar" class="submit-btn">
                                        <i class="fas fa-pencil-alt"></i> <?php echo t('Actualizar Entrada'); ?>
                                    </button>
                                </div>

                                <div class="form-group">
                                    <label for="nombre_archivo">
                                        <i class="fas fa-file-signature"></i> <?php echo t('Nombre del archivo:'); ?>
                                    </label>
                                    <input type="text" id="nombre_archivo" name="nombre_archivo" value="diario_ejercicio.php" 
                                           placeholder="<?php echo t('Nombre del archivo de diario'); ?>">
                                </div>
                            </form>
                        </div>
                    </div>
                </section>

                <!-- Explicación del código principal -->
                <section class="content-section">
                    <h2><i class="fas fa-code"></i> <?php echo t('Código del Sistema Explicado'); ?></h2>
                    
                    <div class="code-explanation">
                        <div class="code-section">
                            <h3>1. <?php echo t('Configuración de la Base de Datos'); ?></h3>
                            <div class="code-example">
                                <pre><code>&lt;?php
// config.php - <?php echo t('Configuración de conexión a MySQL'); ?>
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'diario');

function conectarDB() {
    $conexion = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    
    if ($conexion->connect_error) {
        die("Error de conexión: " . $conexion->connect_error);
    }
    
    $conexion->set_charset("utf8mb4");
    return $conexion;
}
?&gt;</code></pre>
                            </div>
                            <div class="explanation">
                                <p><strong>MySQLi:</strong> <?php echo t('Extensión mejorada para trabajar con MySQL'); ?></p>
                                <p><strong>utf8mb4:</strong> <?php echo t('Soporte completo para caracteres Unicode'); ?></p>
                                <p><strong><?php echo t('Validación de errores:'); ?></strong> <?php echo t('Manejo de errores de conexión'); ?></p>
                            </div>
                        </div>

                        <div class="code-section">
                            <h3>2. <?php echo t('Función para Crear Entradas'); ?></h3>
                            <div class="code-example">
                                <pre><code>&lt;?php
function crearArchivoDia($numero_dia, $nombre, $apellido, $observaciones, $fecha) {
    $contenido_archivo = '&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Día '.$numero_dia.'&lt;/title&gt;
    &lt;link rel="stylesheet" href="../template/css/estilos.css"&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class="diario-container"&gt;
        &lt;div class="diario-pagina"&gt;
            &lt;header class="encabezado-diario"&gt;
                &lt;h1 class="titulo-diario"&gt;Día '.$numero_dia.'&lt;/h1&gt;
                &lt;p class="subtitulo-diario"&gt;'.date("d \\d\\e F, Y", strtotime($fecha)).'&lt;/p&gt;
                &lt;a href="../menu.php" class="boton-volver"&gt;← Volver al Menú&lt;/a&gt;
            &lt;/header&gt;
            
            &lt;main class="contenido-diario"&gt;
                &lt;section class="entrada-completa"&gt;
                    &lt;div class="info-entrada"&gt;
                        &lt;div class="campo-info"&gt;
                            &lt;label&gt;Nombre:&lt;/label&gt;
                            &lt;span&gt;'.$nombre.' '.$apellido.'&lt;/span&gt;
                        &lt;/div&gt;
                        &lt;div class="campo-info"&gt;
                            &lt;label&gt;Fecha:&lt;/label&gt;
                            &lt;span&gt;'.date('d/m/Y H:i:s', strtotime($fecha)).'&lt;/span&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    
                    &lt;div class="contenido-entrada"&gt;
                        &lt;h3&gt;Reflexiones del día&lt;/h3&gt;
                        &lt;div class="texto-entrada"&gt;
                            '.nl2br($observaciones).'
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/section&gt;
            &lt;/main&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;';

    $carpeta_registros = "registros";
    if (!file_exists($carpeta_registros)) {
        mkdir($carpeta_registros, 0777, true);
    }

    $nombre_archivo = "$carpeta_registros/Dia $numero_dia.php";
    file_put_contents($nombre_archivo, $contenido_archivo);
}
?&gt;</code></pre>
                            </div>
                            <div class="explanation">
                                <p><strong>file_put_contents():</strong> <?php echo t('Crea el archivo automáticamente si no existe'); ?></p>
                                <p><strong>nl2br():</strong> <?php echo t('Convierte saltos de línea en etiquetas &lt;br&gt; para HTML'); ?></p>
                                <p><strong>mkdir():</strong> <?php echo t('Crea directorios recursivamente si no existen'); ?></p>
                            </div>
                        </div>

                        <div class="code-section">
                            <h3>3. <?php echo t('Procesamiento del Formulario'); ?></h3>
                            <div class="code-example">
                                <pre><code>&lt;?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // <?php echo t('Sanitizar entradas para prevenir XSS'); ?>
    $nombre = htmlspecialchars($_POST['nombre']);
    $apellido = htmlspecialchars($_POST['apellido']);
    $observaciones = htmlspecialchars($_POST['observaciones']);
    $fecha = date('Y-m-d H:i:s');
    
    // <?php echo t('Obtener próximo número de día desde la base de datos'); ?>
    $numero_dia = obtenerProximoDia();
    
    // <?php echo t('Guardar en base de datos'); ?>
    if (guardarEntradaDB($numero_dia, $nombre, $apellido, $observaciones, $fecha)) {
        // <?php echo t('Crear archivo físico'); ?>
        crearArchivoDia($numero_dia, $nombre, $apellido, $observaciones, $fecha);
        
        // <?php echo t('Redirigir al menú con confirmación'); ?>
        header("Location: menu.php?creado=$numero_dia");
        exit();
    } else {
        \$error = t("Error al guardar la entrada en la base de datos");
    }
}
?&gt;</code></pre>
                            </div>
                            <div class="explanation">
                                <p><strong>htmlspecialchars():</strong> <?php echo t('Previene ataques XSS escapando caracteres especiales'); ?></p>
                                <p><strong>header():</strong> <?php echo t('Redirige al usuario después de procesar el formulario'); ?></p>
                                <p><strong><?php echo t('Validación:'); ?></strong> <?php echo t('Verifica que el guardado en BD fue exitoso'); ?></p>
                            </div>
                        </div>

                        <div class="code-section">
                            <h3>4. <?php echo t('Sistema de Búsqueda Avanzado'); ?></h3>
                            <div class="code-example">
                                <pre><code>&lt;?php
function buscarEntradas($termino) {
    $conexion = conectarDB();
    
    // <?php echo t('Extraer número si se busca "Día X"'); ?>
    $numero_dia = null;
    if (preg_match('/(\d+)/', $termino, $matches)) {
        $numero_dia = intval($matches[1]);
    }

    $termino_limpio = trim(preg_replace('/día\s*/i', '', $termino));
    $termino_like = "%" . $termino_limpio . "%";

    if ($numero_dia !== null) {
        // <?php echo t('Búsqueda incluyendo número de día'); ?>
        $stmt = $conexion->prepare("SELECT numero_dia, fecha_creacion, nombre, apellido, observaciones 
                                   FROM registros 
                                   WHERE nombre LIKE ? 
                                      OR apellido LIKE ? 
                                      OR observaciones LIKE ? 
                                      OR numero_dia = ?
                                   ORDER BY numero_dia DESC");
        $stmt->bind_param("sssi", $termino_like, $termino_like, $termino_like, $numero_dia);
    } else {
        // <?php echo t('Búsqueda solo por texto'); ?>
        $stmt = $conexion->prepare("SELECT numero_dia, fecha_creacion, nombre, apellido, observaciones 
                                   FROM registros 
                                   WHERE nombre LIKE ? 
                                      OR apellido LIKE ? 
                                      OR observaciones LIKE ? 
                                   ORDER BY numero_dia DESC");
        $stmt->bind_param("sss", $termino_like, $termino_like, $termino_like);
    }

    $stmt->execute();
    return $stmt->get_result();
}
?&gt;</code></pre>
                            </div>
                            <div class="explanation">
                                <p><strong>Prepared Statements:</strong> <?php echo t('Previene inyecciones SQL'); ?></p>
                                <p><strong><?php echo t('Búsqueda flexible:'); ?></strong> <?php echo t('Busca en múltiples campos'); ?></p>
                                <p><strong><?php echo t('Expresiones regulares:'); ?></strong> <?php echo t('Detecta búsquedas por número de día'); ?></p>
                            </div>
                        </div>
                    </div>
                </section>

                <!-- Estructura de la base de datos -->
                <section class="content-section">
                    <h2><i class="fas fa-database"></i> <?php echo t('Estructura de la Base de Datos'); ?></h2>
                    
                    <div class="database-structure">
                        <div class="table-schema">
                            <h3><?php echo t('Tabla:'); ?> registros</h3>
                            <table class="schema-table">
                                <thead>
                                    <tr>
                                        <th><?php echo t('Campo'); ?></th>
                                        <th><?php echo t('Tipo'); ?></th>
                                        <th><?php echo t('Descripción'); ?></th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td>id</td>
                                        <td>INT AUTO_INCREMENT</td>
                                        <td><?php echo t('Clave primaria'); ?></td>
                                    </tr>
                                    <tr>
                                        <td>numero_dia</td>
                                        <td>INT</td>
                                        <td><?php echo t('Número consecutivo del día'); ?></td>
                                    </tr>
                                    <tr>
                                        <td>nombre</td>
                                        <td>VARCHAR(100)</td>
                                        <td><?php echo t('Nombre del usuario'); ?></td>
                                    </tr>
                                    <tr>
                                        <td>apellido</td>
                                        <td>VARCHAR(100)</td>
                                        <td><?php echo t('Apellido del usuario'); ?></td>
                                    </tr>
                                    <tr>
                                        <td>observaciones</td>
                                        <td>TEXT</td>
                                        <td><?php echo t('Contenido de la entrada'); ?></td>
                                    </tr>
                                    <tr>
                                        <td>fecha_creacion</td>
                                        <td>DATETIME</td>
                                        <td><?php echo t('Fecha y hora de creación'); ?></td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                        
                        <div class="sql-code">
                            <h4><?php echo t('Script SQL para crear la tabla:'); ?></h4>
                            <pre><code>CREATE TABLE registros (
    id INT AUTO_INCREMENT PRIMARY KEY,
    numero_dia INT NOT NULL,
    nombre VARCHAR(100) NOT NULL,
    apellido VARCHAR(100) NOT NULL,
    observaciones TEXT NOT NULL,
    fecha_creacion DATETIME NOT NULL,
    UNIQUE KEY unique_numero_dia (numero_dia)
);</code></pre>
                        </div>
                    </div>
                </section>

                <!-- Ejercicios prácticos -->
                <section class="content-section">
                    <h2><i class="fas fa-tasks"></i> <?php echo t('Ejercicios para Practicar'); ?></h2>
                    
                    <div class="steps">
                        <div class="step">
                            <h3><?php echo t('Ejercicio'); ?> 1: <?php echo t('Añadir Categorías'); ?></h3>
                            <p><?php echo t('Modifica el sistema para que cada entrada pueda tener una categoría (Trabajo, Personal, Estudio, etc.)'); ?></p>
                            <div class="exercise-hint">
                                <h5><?php echo t('Pistas:'); ?></h5>
                                <ul>
                                    <li><?php echo t('Añade un campo "categoria" en la tabla registros'); ?></li>
                                    <li><?php echo t('Modifica el formulario para incluir un select de categorías'); ?></li>
                                    <li><?php echo t('Actualiza la función crearArchivoDia() para mostrar la categoría'); ?></li>
                                </ul>
                            </div>
                        </div>
                        
                        <div class="step">
                            <h3><?php echo t('Ejercicio'); ?> 2: <?php echo t('Sistema de Etiquetas'); ?></h3>
                            <p><?php echo t('Implementa un sistema de etiquetas donde cada entrada pueda tener múltiples etiquetas'); ?></p>
                            <div class="exercise-hint">
                                <h5>Pistas:</h5>
                                <ul>
                                    <li><?php echo t('Crea una tabla "etiquetas" y una tabla intermedia "registro_etiquetas"'); ?></li>
                                    <li><?php echo t('Usa checkboxes en el formulario para seleccionar etiquetas'); ?></li>
                                    <li><?php echo t('Implementa una función para guardar las relaciones'); ?></li>
                                </ul>
                            </div>
                        </div>
                        
                        <div class="step">
                            <h3><?php echo t('Ejercicio'); ?> 3: <?php echo t('Backup Automático'); ?></h3>
                            <p><?php echo t('Crea una función para hacer backup de todas las entradas en un archivo ZIP'); ?></p>
                            <div class="exercise-hint">
                                <h5>Pistas:</h5>
                                <ul>
                                    <li><?php echo t('Investiga la clase ZipArchive de PHP'); ?></li>
                                    <li><?php echo t('Crea un script que recorra todos los archivos de la carpeta registros'); ?></li>
                                    <li><?php echo t('Añade un botón en el menú para descargar el backup'); ?></li>
                                </ul>
                            </div>
                        </div>
                    </div>
                </section>

                <!-- Flujo de trabajo completo -->
                <section class="content-section">
                    <h2><i class="fas fa-project-diagram"></i> <?php echo t('Flujo de Trabajo Completo'); ?></h2>
                    
                    <div class="workflow">
                        <div class="workflow-step">
                            <div class="step-number">1</div>
                            <h3><?php echo t('Usuario completa formulario'); ?></h3>
                            <p><?php echo t('El usuario ingresa nombre, apellido y observaciones del día'); ?></p>
                        </div>
                        
                        <div class="workflow-step">
                            <div class="step-number">2</div>
                            <h3>PHP <?php echo t('procesa los datos'); ?></h3>
                            <p><?php echo t('El servidor sanitiza los datos y determina el próximo número de día'); ?></p>
                        </div>
                        
                        <div class="workflow-step">
                            <div class="step-number">3</div>
                            <h3><?php echo t('Guardado en Base de Datos'); ?></h3>
                            <p><?php echo t('Los datos se almacenan en la tabla registros usando MySQLi'); ?></p>
                        </div>
                        
                        <div class="workflow-step">
                            <div class="step-number">4</div>
                            <h3><?php echo t('Generación de Archivo'); ?></h3>
                            <p><?php echo t('Se crea un archivo PHP con la entrada formateada en HTML'); ?></p>
                        </div>
                        
                        <div class="workflow-step">
                            <div class="step-number">5</div>
                            <h3><?php echo t('Redirección al menú'); ?></h3>
                            <p><?php echo t('El usuario es redirigido al menú principal con confirmación'); ?></p>
                        </div>
                    </div>
                </section>

                <!-- Evaluación -->
                <section class="content-section">
                    <h2><i class="fas fa-graduation-cap"></i> <?php echo t('Criterios de Evaluación'); ?></h2>
                    
                    <div class="evaluation-criteria">
                        <div class="criterion">
                            <h3>✅ <?php echo t('Funcionalidad Básica (40%)'); ?></h3>
                            <ul>
                                <li><?php echo t('Crear nuevas entradas correctamente'); ?></li>
                                <li><?php echo t('Listar todas las entradas en el menú'); ?></li>
                                <li><?php echo t('Editar entradas existentes'); ?></li>
                                <li><?php echo t('Eliminar entradas con confirmación'); ?></li>
                            </ul>
                        </div>
                        
                        <div class="criterion">
                            <h3>✅ <?php echo t('Base de Datos (30%)'); ?></h3>
                            <ul>
                                <li><?php echo t('Conexión correcta a MySQL'); ?></li>
                                <li><?php echo t('Uso de prepared statements'); ?></li>
                                <li><?php echo t('Manejo de errores de conexión'); ?></li>
                                <li><?php echo t('Estructura de tabla adecuada'); ?></li>
                            </ul>
                        </div>
                        
                        <div class="criterion">
                            <h3>✅ <?php echo t('Seguridad (20%)'); ?></h3>
                            <ul>
                                <li><?php echo t('Sanitización de entradas (htmlspecialchars)'); ?></li>
                                <li><?php echo t('Prevención de SQL injection'); ?></li>
                                <li><?php echo t('Validación de datos del formulario'); ?></li>
                            </ul>
                        </div>
                        
                        <div class="criterion">
                            <h3>✅ UX/UI (10%)</h3>
                            <ul>
                                <li><?php echo t('Interfaz intuitiva y responsive'); ?></li>
                                <li><?php echo t('Mensajes de confirmación y error'); ?></li>
                                <li><?php echo t('Navegación clara entre secciones'); ?></li>
                            </ul>
                        </div>
                    </div>
                </section>

                <!-- Recursos adicionales -->
                <section class="content-section">
                    <h2><i class="fas fa-book"></i> <?php echo t('Recursos Adicionales'); ?></h2>
                    
                    <div class="resources">
                        <a href="https://www.php.net/manual/es/book.mysqli.php" class="resource-link" target="_blank">
                            <i class="fas fa-external-link-alt"></i>
                            <span><?php echo t('Documentación Oficial de MySQLi'); ?></span>
                        </a>
                        
                        <a href="https://www.php.net/manual/es/function.file-put-contents.php" class="resource-link" target="_blank">
                            <i class="fas fa-external-link-alt"></i>
                            <span><?php echo t('Función'); ?> file_put_contents()</span>
                        </a>
                        
                        <a href="https://www.w3schools.com/php/php_form_validation.asp" class="resource-link" target="_blank">
                            <i class="fas fa-external-link-alt"></i>
                            <span><?php echo t('Validación de Formularios PHP'); ?></span>
                        </a>
                    </div>
                </section>
            </article>
        </div>
    </main>

    <?php include '../footer.php'; ?>

    <script src="../template/js/header.js"></script>
    <script src="template/js/diario_ejercicio.js"></script>
</body>
</html>

Try the Diary System

Use the following controls to try the personal diary functions in real time:

Diary Control Panel

System Code Explained

1. Database Configuration

<?php
// config.php - Configuración de conexión a MySQLdefine('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'diario');

function conectarDB() {
    $conexion = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    
    if ($conexion->connect_error) {
        die("Error de conexión: " . $conexion->connect_error);
    }
    
    $conexion->set_charset("utf8mb4");
    return $conexion;
}
?>

MySQLi: Improved extension for working with MySQL

utf8mb4: Full support for Unicode characters

Error Validation: Connection error handling

2. Function to Create Entries

<?php
function crearArchivoDia($numero_dia, $nombre, $apellido, $observaciones, $fecha) {
    $contenido_archivo = '<html>
<head>
    <title>Día '.$numero_dia.'</title>
    <link rel="stylesheet" href="../template/css/estilos.css">
</head>
<body>
    <div class="diario-container">
        <div class="diario-pagina">
            <header class="encabezado-diario">
                <h1 class="titulo-diario">Día '.$numero_dia.'</h1>
                <p class="subtitulo-diario">'.date("d \\d\\e F, Y", strtotime($fecha)).'</p>
                <a href="../menu.php" class="boton-volver">← Volver al Menú</a>
            </header>
            
            <main class="contenido-diario">
                <section class="entrada-completa">
                    <div class="info-entrada">
                        <div class="campo-info">
                            <label>Nombre:</label>
                            <span>'.$nombre.' '.$apellido.'</span>
                        </div>
                        <div class="campo-info">
                            <label>Fecha:</label>
                            <span>'.date('d/m/Y H:i:s', strtotime($fecha)).'</span>
                        </div>
                    </div>
                    
                    <div class="contenido-entrada">
                        <h3>Reflexiones del día</h3>
                        <div class="texto-entrada">
                            '.nl2br($observaciones).'
                        </div>
                    </div>
                </section>
            </main>
        </div>
    </div>
</body>
</html>';

    $carpeta_registros = "registros";
    if (!file_exists($carpeta_registros)) {
        mkdir($carpeta_registros, 0777, true);
    }

    $nombre_archivo = "$carpeta_registros/Dia $numero_dia.php";
    file_put_contents($nombre_archivo, $contenido_archivo);
}
?>

file_put_contents(): Automatically creates the file if it doesn't exist

nl2br(): Converts line breaks into <br> tags for HTML

mkdir(): Recursively creates directories if they don't exist

3. Form Processing

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Sanitizar entradas para prevenir XSS    $nombre = htmlspecialchars($_POST['nombre']);
    $apellido = htmlspecialchars($_POST['apellido']);
    $observaciones = htmlspecialchars($_POST['observaciones']);
    $fecha = date('Y-m-d H:i:s');
    
    // Obtener próximo número de día desde la base de datos    $numero_dia = obtenerProximoDia();
    
    // Guardar en base de datos    if (guardarEntradaDB($numero_dia, $nombre, $apellido, $observaciones, $fecha)) {
        // Crear archivo físico        crearArchivoDia($numero_dia, $nombre, $apellido, $observaciones, $fecha);
        
        // Redirigir al menú con confirmación        header("Location: menu.php?creado=$numero_dia");
        exit();
    } else {
        \$error = t("Error al guardar la entrada en la base de datos");
    }
}
?>

htmlspecialchars(): Prevents XSS attacks by escaping special characters

header(): Redirects the user after processing the form

Validation: Verifies that the DB save was successful

4. Advanced Search System

<?php
function buscarEntradas($termino) {
    $conexion = conectarDB();
    
    // Extraer número si se busca "Día X"    $numero_dia = null;
    if (preg_match('/(\d+)/', $termino, $matches)) {
        $numero_dia = intval($matches[1]);
    }

    $termino_limpio = trim(preg_replace('/día\s*/i', '', $termino));
    $termino_like = "%" . $termino_limpio . "%";

    if ($numero_dia !== null) {
        // Búsqueda incluyendo número de día        $stmt = $conexion->prepare("SELECT numero_dia, fecha_creacion, nombre, apellido, observaciones 
                                   FROM registros 
                                   WHERE nombre LIKE ? 
                                      OR apellido LIKE ? 
                                      OR observaciones LIKE ? 
                                      OR numero_dia = ?
                                   ORDER BY numero_dia DESC");
        $stmt->bind_param("sssi", $termino_like, $termino_like, $termino_like, $numero_dia);
    } else {
        // Búsqueda solo por texto        $stmt = $conexion->prepare("SELECT numero_dia, fecha_creacion, nombre, apellido, observaciones 
                                   FROM registros 
                                   WHERE nombre LIKE ? 
                                      OR apellido LIKE ? 
                                      OR observaciones LIKE ? 
                                   ORDER BY numero_dia DESC");
        $stmt->bind_param("sss", $termino_like, $termino_like, $termino_like);
    }

    $stmt->execute();
    return $stmt->get_result();
}
?>

Prepared Statements: Prevents SQL injections

Flexible Search: Searches across multiple fields

Regular Expressions: Detects searches by day number

Database Structure

Table: registros

Field Type Description
id INT AUTO_INCREMENT Primary key
numero_dia INT Day's consecutive number
nombre VARCHAR(100) User's name
apellido VARCHAR(100) User's last name
observaciones TEXT Entry content
fecha_creacion DATETIME Creation date and time

SQL script to create the table:

CREATE TABLE registros (
    id INT AUTO_INCREMENT PRIMARY KEY,
    numero_dia INT NOT NULL,
    nombre VARCHAR(100) NOT NULL,
    apellido VARCHAR(100) NOT NULL,
    observaciones TEXT NOT NULL,
    fecha_creacion DATETIME NOT NULL,
    UNIQUE KEY unique_numero_dia (numero_dia)
);

Exercises to Practice

Exercise 1: Add Categories

Modify the system so each entry can have a category (Work, Personal, Study, etc.)

Hints:
  • Add a "categoria" field in the registros table
  • Modify the form to include a category select
  • Update the crearArchivoDia() function to show the category

Exercise 2: Tagging System

Implement a tagging system where each entry can have multiple tags

Pistas:
  • Create an "etiquetas" table and an intermediate "registro_etiquetas" table
  • Use checkboxes in the form to select tags
  • Implement a function to save the relationships

Exercise 3: Automatic Backup

Create a function to back up all entries into a ZIP file

Pistas:
  • Research PHP's ZipArchive class
  • Create a script that goes through all the files in the registros folder
  • Add a button in the menu to download the backup

Complete Workflow

1

User fills out the form

The user enters name, last name and remarks for the day

2

PHP processes the data

The server sanitizes the data and determines the next day number

3

Saving to the Database

The data is stored in the registros table using MySQLi

4

File Generation

A PHP file is created with the entry formatted in HTML

5

Redirection to the menu

The user is redirected to the main menu with confirmation

Evaluation Criteria

✅ Basic Functionality (40%)

  • Correctly create new entries
  • List all entries in the menu
  • Edit existing entries
  • Delete entries with confirmation

✅ Database (30%)

  • Correct connection to MySQL
  • Use of prepared statements
  • Connection error handling
  • Appropriate table structure

✅ Security (20%)

  • Input sanitization (htmlspecialchars)
  • SQL injection prevention
  • Form data validation

✅ UX/UI (10%)

  • Intuitive and responsive interface
  • Confirmation and error messages
  • Clear navigation between sections

Additional Resources