Ejercicio: Sistema de Diario Personal

Implementa un sistema completo de diario personal con PHP y MySQL

Nivel Intermedio ⏱️ 2-3 horas

Descargar Código Ejemplo

Objetivos de Aprendizaje

Conexión a Base de Datos

Aprender a conectar PHP con MySQL usando MySQLi

CRUD Completo

Implementar Create, Read, Update, Delete de registros

Manipulación de Archivos

Generar archivos PHP dinámicamente

Sistema de Búsqueda

Implementar búsqueda en contenido y metadatos

Requisitos Previos

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

Estado Actual de la Entrada de Demo

Archivo: diario_ejercicio.php EXISTE

Tamaño: 36636 bytes

Última modificación: 2026-09-10 16:12:04

Contenido actual:

<?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>

Prueba el Sistema de Diario

Usa los siguientes controles para probar las funciones del diario personal en tiempo real:

Panel de Control del Diario

Código del Sistema Explicado

1. Configuración de la Base de Datos

<?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: Extensión mejorada para trabajar con MySQL

utf8mb4: Soporte completo para caracteres Unicode

Validación de errores: Manejo de errores de conexión

2. Función para Crear Entradas

<?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(): Crea el archivo automáticamente si no existe

nl2br(): Convierte saltos de línea en etiquetas <br> para HTML

mkdir(): Crea directorios recursivamente si no existen

3. Procesamiento del Formulario

<?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(): Previene ataques XSS escapando caracteres especiales

header(): Redirige al usuario después de procesar el formulario

Validación: Verifica que el guardado en BD fue exitoso

4. Sistema de Búsqueda Avanzado

<?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: Previene inyecciones SQL

Búsqueda flexible: Busca en múltiples campos

Expresiones regulares: Detecta búsquedas por número de día

Estructura de la Base de Datos

Tabla: registros

Campo Tipo Descripción
id INT AUTO_INCREMENT Clave primaria
numero_dia INT Número consecutivo del día
nombre VARCHAR(100) Nombre del usuario
apellido VARCHAR(100) Apellido del usuario
observaciones TEXT Contenido de la entrada
fecha_creacion DATETIME Fecha y hora de creación

Script SQL para crear la tabla:

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)
);

Ejercicios para Practicar

Ejercicio 1: Añadir Categorías

Modifica el sistema para que cada entrada pueda tener una categoría (Trabajo, Personal, Estudio, etc.)

Pistas:
  • Añade un campo "categoria" en la tabla registros
  • Modifica el formulario para incluir un select de categorías
  • Actualiza la función crearArchivoDia() para mostrar la categoría

Ejercicio 2: Sistema de Etiquetas

Implementa un sistema de etiquetas donde cada entrada pueda tener múltiples etiquetas

Pistas:
  • Crea una tabla "etiquetas" y una tabla intermedia "registro_etiquetas"
  • Usa checkboxes en el formulario para seleccionar etiquetas
  • Implementa una función para guardar las relaciones

Ejercicio 3: Backup Automático

Crea una función para hacer backup de todas las entradas en un archivo ZIP

Pistas:
  • Investiga la clase ZipArchive de PHP
  • Crea un script que recorra todos los archivos de la carpeta registros
  • Añade un botón en el menú para descargar el backup

Flujo de Trabajo Completo

1

Usuario completa formulario

El usuario ingresa nombre, apellido y observaciones del día

2

PHP procesa los datos

El servidor sanitiza los datos y determina el próximo número de día

3

Guardado en Base de Datos

Los datos se almacenan en la tabla registros usando MySQLi

4

Generación de Archivo

Se crea un archivo PHP con la entrada formateada en HTML

5

Redirección al menú

El usuario es redirigido al menú principal con confirmación

Criterios de Evaluación

✅ Funcionalidad Básica (40%)

  • Crear nuevas entradas correctamente
  • Listar todas las entradas en el menú
  • Editar entradas existentes
  • Eliminar entradas con confirmación

✅ Base de Datos (30%)

  • Conexión correcta a MySQL
  • Uso de prepared statements
  • Manejo de errores de conexión
  • Estructura de tabla adecuada

✅ Seguridad (20%)

  • Sanitización de entradas (htmlspecialchars)
  • Prevención de SQL injection
  • Validación de datos del formulario

✅ UX/UI (10%)

  • Interfaz intuitiva y responsive
  • Mensajes de confirmación y error
  • Navegación clara entre secciones

Recursos Adicionales