Tu primera web con memoria
El torneo del instituto ha terminado. Quieres que la gente deje un mensaje en una página, y que los mensajes sigan ahí mañana.
Eso es un libro de visitas. Tiene formulario, base de datos y una lista.
Ya sabes hacer cada trozo. Hoy los juntas.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Libro de visitas | Una página donde cada visitante deja un mensaje que se guarda. | index.php |
| Entrada | Un mensaje del libro. Es una fila de la tabla. | Ana: Gran torneo |
| Redirección | Decir al navegador que vaya a otra página, con la cabecera Location. | header("Location: index.php") |
| Servidor de pruebas | Un servidor pequeño en tu ordenador para probar tu página antes de publicarla. | php -S localhost:8000 |
| Plan de pruebas | Una lista de casos que vas a probar y lo que esperas ver. | Nombre vacío: error |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Pruébalo: las últimas entradas
-- Las tres entradas más nuevas: el id mayor va primero.
SELECT name, message FROM guestbook ORDER BY id DESC LIMIT 3;
-- Cambia el 3 por un 2 y ejecuta otra vez.
Ejemplo resuelto: qué lección usa cada trozo
| Trozo del proyecto | Lo aprendiste en | Lo que usas |
|---|---|---|
| Recibir el formulario | Recibir un formulario | $_POST con ?? |
| Comprobar los datos | No te fíes del usuario | trim y strlen |
| Guardar la entrada | Consultas seguras | prepare y execute |
| Leer las entradas | PHP y base de datos | query y fetchAll |
| Escribirlas en la página | Recibir un formulario | htmlspecialchars |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Primera parte: guardar
<?php
// index.php, primera parte: guardar una entrada nueva.
require "db.php"; // crea la conexión $pdo
require "functions.php"; // trae validateEntry
$errors = [];
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$name = trim($_POST["name"] ?? "");
$message = trim($_POST["message"] ?? "");
$errors = validateEntry($name, $message);
if (count($errors) === 0) {
$sql = "INSERT INTO guestbook (name, message) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $message]);
header("Location: index.php"); // evita que recargar repita el envío
exit;
}
}
Pruébalo: validar y escapar
<?php
// Las dos funciones que no necesitan base de datos.
function validateEntry(string $name, string $message): array {
$errors = [];
if (trim($name) === "") {
$errors[] = "Escribe tu nombre.";
}
if (trim($message) === "") {
$errors[] = "Escribe un mensaje.";
} elseif (strlen(trim($message)) > 500) {
$errors[] = "El mensaje es demasiado largo.";
}
return $errors;
}
function renderEntry(string $name, string $message): string {
return "<p><strong>" . htmlspecialchars($name) . "</strong>: " . htmlspecialchars($message) . "</p>";
}
echo count(validateEntry("Ana", "Qué bien lo pasamos")) . " errores\n";
echo renderEntry("Ana", "<b>Hola</b>") . "\n";
echo implode(" ", validateEntry(" ", "")) . "\n";
Repaso rápido: guardar una entrada
Inténtalo
Repaso rápido: guardar una entrada
3 preguntasTus respuestas se corrigen aquí y no se guardan. Una cuenta guarda tus resultados.
Por qué se redirige tras guardar
Si tras guardar escribes la página sin más, el navegador recuerda el envío. Si la recargas, lo repite.
Y la entrada se guarda dos veces.
Con header("Location: ...") y exit, el navegador pide la página de nuevo, sin datos. Recargar ya no repite nada.