Subir archivos a "clases"

This commit is contained in:
2026-09-24 11:13:44 +02:00
parent d1c381d7ac
commit e102298961
2 changed files with 108 additions and 160 deletions
+31 -86
View File
@@ -1,88 +1,53 @@
<?php <?php
require_once '../includes/conexionBD.php'; require_once '../includes/conexionBD.php';
// Definición de la clase Pregunta que representará las preguntas de la trivia
class Pregunta { class Pregunta {
// ATRIBUTOS (Propiedades privadas para encapsular el estado de cada pregunta) private ?int $idPregunta;
private ?int $id_pregunta; // El ID de la pregunta (autoincremental en la BD) private int $idCategoria;
private int $id_categoria; // El ID de la categoría a la que pertenece la pregunta private string $nombrePregunta;
private string $texto_pregunta; // El enunciado de la pregunta private array $respuestas;
private array $respuestas; // Array que guardará la lista de respuestas posibles asociadas a esta pregunta
// CONSTRUCTOR: Inicializa una nueva instancia de la clase Pregunta (sin pedir PDO de forma externa) public function __construct(int $idCategoria = 0, string $nombrePregunta = "", ?int $idPregunta = null) {
public function __construct(int $id_categoria = 0, string $texto_pregunta = "", ?int $id_pregunta = null) { $this->idPregunta = $idPregunta;
$this->id_pregunta = $id_pregunta; // Asigna el ID (null si es una nueva pregunta que no se ha guardado) $this->idCategoria = $idCategoria;
$this->id_categoria = $id_categoria; // Asigna la categoría correspondiente $this->nombrePregunta = $nombrePregunta;
$this->texto_pregunta = $texto_pregunta; // Asigna el texto de la pregunta $this->respuestas = [];
$this->respuestas = []; // Inicializa el contenedor de respuestas como un array vacío
} }
// --- GETTERS Y SETTERS --- public function getIdPregunta(): ?int { return $this->idPregunta; }
// Getter para obtener el ID de la pregunta (solo lectura)
public function getIdPregunta(): ?int {
return $this->id_pregunta;
}
// Getter para obtener el ID de la categoría public function getIdCategoria(): int { return $this->idCategoria; }
public function getIdCategoria(): int { public function setIdCategoria(int $idCategoria): void { $this->idCategoria = $idCategoria; }
return $this->id_categoria;
}
// Setter para cambiar la categoría de la pregunta
public function setIdCategoria(int $id_categoria): void {
$this->id_categoria = $id_categoria;
}
// Getter para obtener el texto de la pregunta public function getNombrePregunta(): string { return $this->nombrePregunta; }
public function getTextoPregunta(): string { public function setNombrePregunta(string $nombrePregunta): void { $this->nombrePregunta = $nombrePregunta; }
return $this->texto_pregunta;
}
// Setter para cambiar el texto de la pregunta
public function setTextoPregunta(string $texto_pregunta): void {
$this->texto_pregunta = $texto_pregunta;
}
// Getter para obtener el array con todas las respuestas cargadas de esta pregunta public function getRespuestas(): array { return $this->respuestas; }
public function getRespuestas(): array {
return $this->respuestas;
}
// --- MÉTODOS DE BASE DE DATOS ---
// Método para guardar una nueva pregunta en la base de datos
public function guardar() { public function guardar() {
// Obtenemos la conexión llamando a tu función unificada del proyecto
$conexion = conexionBD(); $conexion = conexionBD();
// Si devuelve un array significa que ocurrió un error controlado al conectar
if (is_array($conexion)) { if (is_array($conexion)) {
return $conexion; return $conexion;
} }
try { try {
// Preparamos la consulta SQL para insertar la categoría y el texto de la pregunta $sql = "INSERT INTO pregunta (idCategoria, nombrePregunta) VALUES (:idCat, :texto)";
$sql = "INSERT INTO pregunta (id_categoria, texto_pregunta) VALUES (:id_cat, :texto)";
$stmt = $conexion->prepare($sql); $stmt = $conexion->prepare($sql);
// Ejecutamos la consulta asociando los atributos actuales del objeto a los marcadores SQL
$stmt->execute([ $stmt->execute([
':id_cat' => $this->id_categoria, ':idCat' => $this->idCategoria,
':texto' => $this->texto_pregunta ':texto' => $this->nombrePregunta
]); ]);
// Si se guardó correctamente, actualizamos el atributo id_pregunta del objeto con el ID generado en la BD $this->idPregunta = (int)$conexion->lastInsertId();
$this->id_pregunta = (int)$conexion->lastInsertId();
// Devolvemos la respuesta formateada con éxito e ID técnico para tu proyecto
return [ return [
'exito' => 'Pregunta guardada correctamente', 'exito' => 'Pregunta guardada correctamente',
'exito_tecnico' => $this->id_pregunta 'exito_tecnico' => $this->idPregunta
]; ];
} catch (PDOException $error) { } catch (PDOException $error) {
// Si falla la inserción en MySQL, capturamos el error
return [ return [
'error' => 'Ocurrió un error al guardar la pregunta.', 'error' => 'Ocurrió un error al guardar la pregunta.',
'error_tecnico' => $error->getMessage() 'error_tecnico' => $error->getMessage()
@@ -90,30 +55,23 @@ class Pregunta {
} }
} }
// Método para buscar y cargar en memoria todas las respuestas asociadas a esta pregunta concreta
public function cargarRespuestas() { public function cargarRespuestas() {
// Si la pregunta aún no está guardada en la BD (su ID es null), no podemos buscar sus respuestas if ($this->idPregunta === null) return;
if ($this->id_pregunta === null) return;
// Obtenemos la conexión llamando a tu función unificada del proyecto
$conexion = conexionBD(); $conexion = conexionBD();
// Si devuelve un array significa que ocurrió un error al conectar
if (is_array($conexion)) { if (is_array($conexion)) {
return $conexion; return $conexion;
} }
try { try {
// Consulta SQL adaptada exactamente a tus columnas reales: texto_respuesta y es_correcta $sql = "SELECT idRespuesta, nombreRespuesta, correcta FROM respuesta WHERE idPregunta = :idPreg";
$sql = "SELECT id_respuesta, texto_respuesta, es_correcta FROM respuesta WHERE id_pregunta = :id_preg";
$stmt = $conexion->prepare($sql); $stmt = $conexion->prepare($sql);
$stmt->execute([':id_preg' => $this->id_pregunta]); $stmt->execute([':idPreg' => $this->idPregunta]);
// Guardamos todas las filas encontradas directamente dentro del array de respuestas del objeto
$this->respuestas = $stmt->fetchAll(PDO::FETCH_ASSOC); $this->respuestas = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $error) { } catch (PDOException $error) {
// Capturamos cualquier excepción de base de datos
return [ return [
'error' => 'Ocurrió un error al cargar las respuestas.', 'error' => 'Ocurrió un error al cargar las respuestas.',
'error_tecnico' => $error->getMessage() 'error_tecnico' => $error->getMessage()
@@ -121,43 +79,30 @@ class Pregunta {
} }
} }
// Método estático para obtener un listado de preguntas aleatorias filtradas por una categoría public static function obtenerPorCategoria(int $idCategoria, int $limite = 10) {
public static function obtenerPorCategoria(int $id_categoria, int $limite = 10) {
// Obtenemos la conexión llamando a tu función unificada del proyecto
$conexion = conexionBD(); $conexion = conexionBD();
// Si devuelve un array significa que ocurrió un error al conectar
if (is_array($conexion)) { if (is_array($conexion)) {
return $conexion; return $conexion;
} }
try { try {
// Consulta SQL que filtra por categoría, desordena los resultados al azar (RAND()) y limita la cantidad $sql = "SELECT * FROM pregunta WHERE idCategoria = :idCat ORDER BY RAND() LIMIT :limite";
$sql = "SELECT * FROM pregunta WHERE id_categoria = :id_cat ORDER BY RAND() LIMIT :limite";
$stmt = $conexion->prepare($sql); $stmt = $conexion->prepare($sql);
// Vinculamos los parámetros asegurando que el límite sea interpretado estrictamente como un número entero (PARAM_INT) $stmt->bindValue(':idCat', $idCategoria, PDO::PARAM_INT);
$stmt->bindValue(':id_cat', $id_categoria, PDO::PARAM_INT);
$stmt->bindValue(':limite', $limite, PDO::PARAM_INT); $stmt->bindValue(':limite', $limite, PDO::PARAM_INT);
$stmt->execute(); // Ejecutamos la consulta $stmt->execute();
$preguntas = []; // Array donde amontonaremos los objetos Pregunta resultantes $preguntas = [];
// Recorremos fila por fila los resultados devueltos por la base de datos
while ($datos = $stmt->fetch(PDO::FETCH_ASSOC)) { while ($datos = $stmt->fetch(PDO::FETCH_ASSOC)) {
// Creamos un nuevo objeto Pregunta con los datos de la fila actual $preg = new Pregunta((int)$datos['idCategoria'], $datos['nombrePregunta'], (int)$datos['idPregunta']);
$preg = new Pregunta($datos['id_categoria'], $datos['texto_pregunta'], $datos['id_pregunta']); $preg->cargarRespuestas();
// Llamamos al método interno del objeto para que busque y le pegue sus opciones de respuesta correspondientes
$preg->cargarRespuestas();
// Añadimos el objeto completamente armado al array final
$preguntas[] = $preg; $preguntas[] = $preg;
} }
return $preguntas; // Devolvemos la lista de objetos Pregunta listos para jugar return $preguntas;
} catch (PDOException $error) { } catch (PDOException $error) {
// Capturamos cualquier error en la consulta aleatoria
return [ return [
'error' => 'Ocurrió un error al obtener las preguntas aleatorias.', 'error' => 'Ocurrió un error al obtener las preguntas aleatorias.',
'error_tecnico' => $error->getMessage() 'error_tecnico' => $error->getMessage()
+77 -74
View File
@@ -1,97 +1,98 @@
<?php <?php
require_once '../includes/conexionBD.php'; require_once '../includes/conexionBD.php';
// Definición de la clase Usuario que representará a los usuarios del sistema
class Usuario { class Usuario {
// ATRIBUTOS (Propiedades privadas para proteger los datos de accesos directos externos) private ?int $idUsuario;
private ?int $id_usuario; // El ID del usuario (puede ser null si aún no se ha guardado en la base de datos) private string $nombreUsuario;
private string $nombre_usuario; // El nombre de usuario en texto private string $contrasena;
private string $contrasena; // La contraseña (normalmente encriptada) private string $email;
private string $email; // El correo electrónico del usuario private ?string $avatar;
private ?string $cookie;
private int $aciertos;
private int $victorias;
private int $derrotas;
// CONSTRUCTOR: Se ejecuta automáticamente al crear un nuevo objeto (ya no pide base de datos por parámetro) public function __construct(
public function __construct(string $nombre_usuario = "", string $contrasena = "", string $email = "", ?int $id_usuario = null) { string $nombreUsuario = "",
$this->id_usuario = $id_usuario; // Asigna el ID (por defecto es null si es un registro nuevo) string $contrasena = "",
$this->nombre_usuario = $nombre_usuario; // Asigna el nombre de usuario recibido string $email = "",
$this->contrasena = $contrasena; // Asigna la contraseña recibida ?string $avatar = null,
$this->email = $email; // Asigna el email recibido ?string $cookie = null,
int $aciertos = 0,
int $victorias = 0,
int $derrotas = 0,
?int $idUsuario = null
) {
$this->idUsuario = $idUsuario;
$this->nombreUsuario = $nombreUsuario;
$this->contrasena = $contrasena;
$this->email = $email;
$this->avatar = $avatar;
$this->cookie = $cookie;
$this->aciertos = $aciertos;
$this->victorias = $victorias;
$this->derrotas = $derrotas;
} }
// --- GETTERS Y SETTERS (Métodos públicos para acceder y modificar los datos privados de forma segura) --- public function getIdUsuario(): ?int { return $this->idUsuario; }
// Getter para obtener el ID del usuario (es de solo lectura, no tiene setter)
public function getIdUsuario(): ?int {
return $this->id_usuario;
}
// Getter para obtener el nombre de usuario public function getNombreUsuario(): string { return $this->nombreUsuario; }
public function getNombreUsuario(): string { public function setNombreUsuario(string $nombreUsuario): void { $this->nombreUsuario = $nombreUsuario; }
return $this->nombre_usuario;
}
// Setter para cambiar el nombre de usuario desde fuera de la clase
public function setNombreUsuario(string $nombre_usuario): void {
$this->nombre_usuario = $nombre_usuario;
}
// Getter para obtener la contraseña public function getContrasena(): string { return $this->contrasena; }
public function getContrasena(): string { public function setContrasena(string $contrasena): void { $this->contrasena = $contrasena; }
return $this->contrasena;
}
// Setter para cambiar la contraseña desde fuera de la clase
public function setContrasena(string $contrasena): void {
$this->contrasena = $contrasena;
}
// Getter para obtener el correo electrónico public function getEmail(): string { return $this->email; }
public function getEmail(): string { public function setEmail(string $email): void { $this->email = $email; }
return $this->email;
}
// Setter para cambiar el correo electrónico desde fuera de la clase
public function setEmail(string $email): void {
$this->email = $email;
}
// --- MÉTODOS DE BASE DE DATOS (Lógica de negocio e interacción con SQL) --- public function getAvatar(): ?string { return $this->avatar; }
public function setAvatar(?string $avatar): void { $this->avatar = $avatar; }
public function getCookie(): ?string { return $this->cookie; }
public function setCookie(?string $cookie): void { $this->cookie = $cookie; }
public function getAciertos(): int { return $this->aciertos; }
public function setAciertos(int $aciertos): void { $this->aciertos = $aciertos; }
public function getVictorias(): int { return $this->victorias; }
public function setVictorias(int $victorias): void { $this->victorias = $victorias; }
public function getDerrotas(): int { return $this->derrotas; }
public function setDerrotas(int $derrotas): void { $this->derrotas = $derrotas; }
// Método para registrar/insertar el usuario actual en la base de datos
public function registrar() { public function registrar() {
// Obtenemos la conexión llamando a tu función unificada del proyecto
$conexion = conexionBD(); $conexion = conexionBD();
// Si devuelve un array significa que ocurrió un error controlado al conectar
if (is_array($conexion)) { if (is_array($conexion)) {
return $conexion; return $conexion;
} }
try { try {
// Preparamos la consulta SQL usando marcadores (:nombre, :pass, :email) para evitar inyecciones SQL $sql = "INSERT INTO usuario (nombreUsuario, contrasena, email, avatar, cookie, aciertos, victorias, derrotas)
$sql = "INSERT INTO usuario (nombre_usuario, contrasena, email) VALUES (:nombre, :pass, :email)"; VALUES (:nombre, :pass, :email, :avatar, :cookie, :aciertos, :victorias, :derrotas)";
$stmt = $conexion->prepare($sql); // Prepara la consulta en el servidor de la base de datos $stmt = $conexion->prepare($sql);
// Encriptamos la contraseña con el algoritmo BCRYPT antes de guardarla por seguridad
$passHash = password_hash($this->contrasena, PASSWORD_BCRYPT); $passHash = password_hash($this->contrasena, PASSWORD_BCRYPT);
// Ejecutamos la consulta pasando los valores reales que sustituirán a los marcadores
$stmt->execute([ $stmt->execute([
':nombre' => $this->nombre_usuario, ':nombre' => $this->nombreUsuario,
':pass' => $passHash, // Guardamos la contraseña ya encriptada ':pass' => $passHash,
':email' => $this->email ':email' => $this->email,
':avatar' => $this->avatar,
':cookie' => $this->cookie,
':aciertos' => $this->aciertos,
':victorias' => $this->victorias,
':derrotas' => $this->derrotas
]); ]);
// Si la inserción fue exitosa, recuperamos el ID generado por la base de datos y lo asignamos al objeto $this->idUsuario = (int)$conexion->lastInsertId();
$this->id_usuario = (int)$conexion->lastInsertId();
// Devolvemos una respuesta de éxito idéntica al formato del resto de tus clases
return [ return [
'exito' => 'Usuario registrado correctamente', 'exito' => 'Usuario registrado correctamente',
'exito_tecnico' => $this->id_usuario 'exito_tecnico' => $this->idUsuario
]; ];
} catch (PDOException $error) { } catch (PDOException $error) {
// Si ocurre algún fallo en la consulta, capturamos el error y devolvemos la respuesta controlada
return [ return [
'error' => 'Ocurrió un error al registrar el usuario.', 'error' => 'Ocurrió un error al registrar el usuario.',
'error_tecnico' => $error->getMessage() 'error_tecnico' => $error->getMessage()
@@ -99,41 +100,43 @@ class Usuario {
} }
} }
// Método estático para buscar un usuario por su ID sin necesidad de instanciar el objeto previamente
public static function buscarPorId($id) { public static function buscarPorId($id) {
// Obtenemos la conexión llamando a tu función unificada del proyecto
$conexion = conexionBD(); $conexion = conexionBD();
// Si devuelve un array significa que ocurrió un error controlado al conectar
if (is_array($conexion)) { if (is_array($conexion)) {
return $conexion; return $conexion;
} }
try { try {
// Preparamos la consulta SQL filtrando por el ID recibido $sql = "SELECT * FROM usuario WHERE idUsuario = :id";
$sql = "SELECT * FROM usuario WHERE id_usuario = :id";
$stmt = $conexion->prepare($sql); $stmt = $conexion->prepare($sql);
$stmt->execute([':id' => $id]); // Ejecutamos la consulta $stmt->execute([':id' => $id]);
// Obtenemos el registro en forma de array asociativo
$datos = $stmt->fetch(PDO::FETCH_ASSOC); $datos = $stmt->fetch(PDO::FETCH_ASSOC);
// Si el usuario existe en la base de datos, creamos y devolvemos un nuevo objeto Usuario con sus datos
if ($datos) { if ($datos) {
return new Usuario($datos['nombre_usuario'], $datos['contrasena'], $datos['email'], $datos['id_usuario']); return new Usuario(
$datos['nombreUsuario'],
$datos['contrasena'],
$datos['email'],
$datos['avatar'],
$datos['cookie'],
(int)$datos['aciertos'],
(int)$datos['victorias'],
(int)$datos['derrotas'],
(int)$datos['idUsuario']
);
} }
// Si la consulta termina pero no encuentra filas, devolvemos un aviso de error controlado
return [ return [
'error' => 'No se encontró ningún usuario con ese ID.' 'error' => 'No se encontró ningún usuario con ese ID.'
]; ];
} catch (PDOException $error) { } catch (PDOException $error) {
// Si ocurre algún fallo en la consulta SQL, capturamos el error
return [ return [
'error' => 'Ocurrió un error al buscar el usuario.', 'error' => 'Ocurrió un error al buscar el usuario.',
'error_tecnico' => $error->getMessage() 'error_tecnico' => $error->getMessage()
]; ];
} }
} }
} }