diff --git a/clases/ClasePregunta.php b/clases/ClasePregunta.php new file mode 100644 index 0000000..b4d6c1b --- /dev/null +++ b/clases/ClasePregunta.php @@ -0,0 +1,115 @@ +db = $db; // Asigna la conexión a la base de datos + $this->id_pregunta = $id_pregunta; // Asigna el ID (null si es una nueva pregunta que no se ha guardado) + $this->id_categoria = $id_categoria; // Asigna la categoría correspondiente + $this->texto_pregunta = $texto_pregunta; // Asigna el texto de la pregunta + $this->respuestas = []; // Inicializa el contenedor de respuestas como un array vacío + } + + // --- GETTERS Y SETTERS --- + + // 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->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 getTextoPregunta(): string { + 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; + } + + // --- MÉTODOS DE BASE DE DATOS --- + + // Método para guardar una nueva pregunta en la base de datos + public function guardar(): bool { + // Preparamos la consulta SQL para insertar la categoría y el texto de la pregunta + $sql = "INSERT INTO pregunta (id_categoria, texto_pregunta) VALUES (:id_cat, :texto)"; + $stmt = $this->db->prepare($sql); + + // Ejecutamos la consulta asociando los atributos actuales del objeto a los marcadores SQL + $resultado = $stmt->execute([ + ':id_cat' => $this->id_categoria, + ':texto' => $this->texto_pregunta + ]); + + // Si se guardó correctamente, actualizamos el atributo id_pregunta del objeto con el ID generado en la BD + if ($resultado) { + $this->id_pregunta = (int)$this->db->lastInsertId(); + return true; // Retorna verdadero si la operación tuvo éxito + } + return false; // Retorna falso si falló el guardado + } + + // Método para buscar y cargar en memoria todas las respuestas asociadas a esta pregunta concreta + public function cargarRespuestas(): void { + // Si la pregunta aún no está guardada en la BD (su ID es null), no podemos buscar sus respuestas + if ($this->id_pregunta === null) return; + + // Consulta SQL para traer las respuestas vinculadas al ID de esta pregunta + $sql = "SELECT id_respuesta, texto_respuesta, es_correcta FROM respuesta WHERE id_pregunta = :id_preg"; + $stmt = $this->db->prepare($sql); + $stmt->execute([':id_preg' => $this->id_pregunta]); + + // Guardamos todas las filas encontradas directamente dentro del array de respuestas del objeto + $this->respuestas = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + // Método estático para obtener un listado de preguntas aleatorias filtradas por una categoría + public static function obtenerPorCategoria(PDO $db, int $id_categoria, int $limite = 10): array { + // Consulta SQL que filtra por categoría, desordena los resultados al azar (RAND()) y limita la cantidad + $sql = "SELECT * FROM pregunta WHERE id_categoria = :id_cat ORDER BY RAND() LIMIT :limite"; + $stmt = $db->prepare($sql); + + // Vinculamos los parámetros asegurando que el límite sea interpretado estrictamente como un número entero (PARAM_INT) + $stmt->bindValue(':id_cat', $id_categoria, PDO::PARAM_INT); + $stmt->bindValue(':limite', $limite, PDO::PARAM_INT); + $stmt->execute(); // Ejecutamos la consulta + + $preguntas = []; // Array donde amontonaremos los objetos Pregunta resultantes + + // Recorremos fila por fila los resultados devueltos por la base de datos + while ($datos = $stmt->fetch(PDO::FETCH_ASSOC)) { + // Creamos un nuevo objeto Pregunta con los datos de la fila actual + $preg = new Pregunta($db, $datos['id_categoria'], $datos['texto_pregunta'], $datos['id_pregunta']); + + // 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; + } + return $preguntas; // Devolvemos la lista de objetos Pregunta listos para jugar + } +} \ No newline at end of file diff --git a/clases/ClaseUsuario.php b/clases/ClaseUsuario.php new file mode 100644 index 0000000..87a128a --- /dev/null +++ b/clases/ClaseUsuario.php @@ -0,0 +1,102 @@ +db = $db; // Asigna la conexión a la base de datos al atributo interno + $this->id_usuario = $id_usuario; // Asigna el ID (por defecto es null si es un registro nuevo) + $this->nombre_usuario = $nombre_usuario; // Asigna el nombre de usuario recibido + $this->contrasena = $contrasena; // Asigna la contraseña recibida + $this->email = $email; // Asigna el email recibido + } + + // --- GETTERS Y SETTERS (Métodos públicos para acceder y modificar los datos privados de forma segura) --- + + // 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->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; + } + + // 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; + } + + // 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) --- + + // Método para registrar/insertar el usuario actual en la base de datos + public function registrar(): bool { + // Preparamos la consulta SQL usando marcadores (:nombre, :pass, :email) para evitar inyecciones SQL + $sql = "INSERT INTO usuario (nombre_usuario, contrasena, email) VALUES (:nombre, :pass, :email)"; + $stmt = $this->db->prepare($sql); // Prepara la consulta en el servidor de la base de datos + + // Encriptamos la contraseña con el algoritmo BCRYPT antes de guardarla por seguridad + $passHash = password_hash($this->contrasena, PASSWORD_BCRYPT); + + // Ejecutamos la consulta pasando los valores reales que sustituirán a los marcadores + $resultado = $stmt->execute([ + ':nombre' => $this->nombre_usuario, + ':pass' => $passHash, // Guardamos la contraseña ya encriptada + ':email' => $this->email + ]); + + // Si la inserción fue exitosa, recuperamos el ID generado por la base de datos y lo asignamos al objeto + if ($resultado) { + $this->id_usuario = (int)$this->db->lastInsertId(); + return true; // Devuelve verdadero indicando que se registró correctamente + } + return false; // Devuelve falso si hubo algún error en la inserción + } + + // Método estático para buscar un usuario por su ID sin necesidad de instanciar el objeto previamente + public static function buscarPorId(PDO $db, int $id): ?Usuario { + // Preparamos la consulta SQL filtrando por el ID recibido + $sql = "SELECT * FROM usuario WHERE id_usuario = :id"; + $stmt = $db->prepare($sql); + $stmt->execute([':id' => $id]); // Ejecutamos la consulta + + // Obtenemos el registro en forma de array asociativo + $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) { + return new Usuario($db, $datos['nombre_usuario'], $datos['contrasena'], $datos['email'], $datos['id_usuario']); + } + return null; // Si no se encuentra el usuario, devolvemos null + } +} + +