Ver Mensaje Individual
  #1 (permalink)  
Antiguo 20/11/2013, 15:34
Avatar de Alexis88
Alexis88
Philosopher
 
Fecha de Ingreso: noviembre-2011
Ubicación: Tacna, Perú
Mensajes: 5.552
Antigüedad: 12 años, 5 meses
Puntos: 977
Problema con conexión a BD y clases

Hola amigos del foro, hace unas semanas, publiqué un hilo acerca del problema del que trataré ahora, en aquel momento creí que lo había solucionado, pero después de analizar bien todo y realizar múltiples pruebas, comprobé que no fue así.

Sucede lo siguiente:

Tengo un formulario de datos, los cuales envío a un archivo que invoca a cuatro clases: para la conexión, para desinfectar los datos (XSS, SQL Injection), para validarlos (que los datos respeten el formato) y para guardarlos en la BD (esta clase también realiza otras consultas).

El problema se suscita cuando intento utilizar más de 1 método de la clase de guarda los datos, el código de ese archivo es el siguiente:
Código PHP:
Ver original
  1. <?php
  2. //Incluimos el archivo de conexión a la Base de datos y nos conectamos
  3. include("conexion.php");
  4. $miConexion = new Cls_Conexion();
  5.  
  6. //Incluimos el archivo de seguridad de datos
  7. include("seguridad.php");
  8. $desinfectar = new Cls_Desinfeccion();
  9.  
  10. //Incluimos el archivo de consultas a la Base de datos
  11. include("consultas.php");
  12. $miConsulta = new Cls_Consultas($miConexion->conexion);
  13.  
  14. //Incluimos el archivo de scripts PHP
  15. include("scripts.php");
  16. $scripts = new Cls_Scripts();
  17.  
  18. //Código
  19. $codigo = $scripts->codigo();
  20. $verificarCodigo = $miConsulta->codigo($codigo);
  21. if ($verificarCodigo->num_rows) {
  22.     do {
  23.         $codigo = $scripts->codigo();
  24.         $verificarCodigo = $miConsulta->codigo($codigo);
  25.     } while ($verificarCodigo = $miConsulta->codigo($codigo));
  26.     $verificarCodigo->free();
  27. }
  28.  
  29. //Nombre
  30. $nombre = (strlen($_POST["nombre"]) && isset($_POST["nombre"]) && !is_null($_POST["nombre"])) ? $scripts->validarNomApe($desinfectar->sanitize($miConexion->conexion, $_POST["nombre"])) : $scripts->formulario();
  31. if (is_null($nombre)) $scripts->formulario("Debe de ingresar su nombre en un formato válido");
  32.  
  33. //Apellidos
  34. $apellidos = (strlen($_POST["apellidos"]) && isset($_POST["apellidos"]) && !is_null($_POST["apellidos"])) ? $scripts->validarNomApe($desinfectar->sanitize($miConexion->conexion, $_POST["apellidos"])) : $scripts->formulario();
  35. if (is_null($apellidos)) $scripts->formulario("Debe de ingresar sus apellidos en un formato válido");
  36.  
  37. //E-Mail
  38. $email = (strlen($_POST["email"]) && isset($_POST["email"]) && !is_null($_POST["email"])) ? $scripts->validarEMail($desinfectar->sanitize($miConexion->conexion, $_POST["email"])) : $scripts->formulario();
  39. if (is_null($email))
  40.     $scripts->formulario("Debe de ingresar su E-Mail en un formato válido");
  41. else {
  42.     $verificarEmail = $miConsulta->email($email);
  43.     if ($verificarEmail->num_rows) {
  44.         $scripts->formulario("El E-Mail ingresado se encuentra registrado. Por favor, ingrese otro.");
  45.         $email = NULL;
  46.         $verificarEmail->free();
  47.     }
  48. }
  49.  
  50. //Domicilio
  51. $domicilio = (strlen($_POST["domicilio"]) && isset($_POST["domicilio"]) && !is_null($_POST["domicilio"])) ? $scripts->validarDomicilio($desinfectar->sanitize($miConexion->conexion, $_POST["domicilio"])) : $scripts->formulario();
  52. if (is_null($domicilio)) $scripts->formulario("Debe de ingresar su dirección domiciliaria en un formato válido y utilizando menos de 256 caracteres");
  53.  
  54. //Fecha de nacimiento
  55. $fechanac = (strlen($_POST["fechanac"]) && isset($_POST["fechanac"]) && !is_null($_POST["fechanac"])) ? $scripts->validarFechNac($desinfectar->sanitize($miConexion->conexion, $_POST["fechanac"])) : $scripts->formulario();
  56. if (is_null($fechanac)) $scripts->formulario("Debe de ingresar la fecha de su nacimiento en un formato válido");
  57.  
  58. //País
  59. $pais = (strlen($_POST["pais"]) && isset($_POST["pais"]) && !is_null($_POST["pais"])) ? $scripts->validarPaisCiudad($desinfectar->sanitize($miConexion->conexion, $_POST["pais"])) : $scripts->formulario();
  60. if (is_null($pais)) $scripts->formulario("Debe de elegir un país de la lista");
  61.  
  62. //Ciudad
  63. $ciudad = (strlen($_POST["ciudad"]) && isset($_POST["ciudad"]) && !is_null($_POST["ciudad"])) ? $scripts->validarPaisCiudad($desinfectar->sanitize($miConexion->conexion, $_POST["ciudad"])) : $scripts->formulario();
  64. if (is_null($ciudad)) $scripts->formulario("Debe de elegir una ciudad de la lista");
  65.  
  66. //Añadimos todos los datos a un array que será enviado a la función de procesamiento de datos
  67. $datos = array(
  68.             "codigo" => $codigo,
  69.             "nombre" => $nombre,
  70.             "apellidos" => $apellidos,
  71.             "email" => $email,
  72.             "domicilio" => $domicilio,
  73.             "fechanac" => $fechanac,
  74.             "pais" => $pais,
  75.             "ciudad" => $ciudad
  76.         );
  77.        
  78. $bandera = true; //Comodín para determinar si se guardarán o no los datos
  79. foreach ($datos as $dato)
  80.     if (is_null($dato)) {
  81.         $bandera = false;
  82.         break;
  83.     }
  84.  
  85. if ($bandera)
  86.     //Guardamos los datos del formulario en la Base de datos
  87.     if ($miConsulta->guardarForm($datos))
  88.         echo "Los datos han sido guardados satisfactoriamente";
  89.     else
  90.         echo "Ha ocurrido un error al intentar guardar los datos";
  91. ?>

La conexión la realizo de esta forma:
Código PHP:
Ver original
  1. <?php
  2. class Cls_Conexion {
  3.     public $conexion;
  4.  
  5.     function __construct() {
  6.         //Conexión a la base de datos
  7.         $servidor = "localhost"; //Nombre del servidor
  8.         $usuario = "root"; //Nombre de usuario en tu servidor
  9.         $password = "miclave"; //Contraseña del usuario
  10.         $base = "bd_formulario"; //Nombre de la Base de Datos
  11.  
  12.         //Se realiza la conexión
  13.         return $this->conexion = new mysqli($servidor, $usuario, $password, $base) or exit("Se ha producido un error en la conexión al servidor");
  14.     }
  15.  
  16.     function __destruct() {
  17.         $this->conexion->close();
  18.     }
  19. }
  20. ?>

Y la clase que contiene los métodos que realizan consultas a la BD es el siguiente:
Código PHP:
Ver original
  1. <?php
  2. class Cls_Consultas {
  3.     public $conexion;
  4.  
  5.     function __construct($conex) {
  6.         $this->conexion = $conex;
  7.     }
  8.  
  9.     function paises() {
  10.         return $this->conexion->query("CALL USP_listCountries()");
  11.     }
  12.  
  13.     function ciudades($pais) {
  14.         return $this->conexion->query(sprintf("CALL USP_listCities(%d)", $pais));
  15.     }
  16.  
  17.     function codigo($codigo) {
  18.         return $this->conexion->query(sprintf("CALL USP_validateCode('%s')", $codigo));
  19.     }
  20.  
  21.     function email($email) {       
  22.         return $this->conexion->query(sprintf("CALL USP_validateEmail('%s')", $email));
  23.     }
  24.  
  25.     function guardarForm($datos) {
  26.         return $this->conexion->query(sprintf("CALL USP_saveForm('%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
  27.                 $datos["codigo"],
  28.                 $datos["nombre"],
  29.                 $datos["apellidos"],
  30.                 $datos["email"],
  31.                 $datos["domicilio"],
  32.                 $datos["fechanac"],
  33.                 $datos["pais"],
  34.                 $datos["ciudad"]
  35.             ));
  36.     }
  37. }
  38. ?>

Luego de varias pruebas, he notado que el problema se da luego de la llamada al método codigo con el que genero un código numérico aleatorio, ese bloque se ejecuta sin problemas, incluso probé insertando una línea de impresión antes del bucle Do-While para ver si de verdad estaba trabajando el método y no me mostró la impresión, con lo cual, comprobé que todo marchaba bien con dicho método, sin embargo, cuando intento llamar a los métodos email (con el que busco en la BD si ya se registró un email como el ingresado en el formulario) y guardarForm (para guardar los datos en la BD), el método email no muestra el mensaje de advertencia aún cuando ingreso un email existente en la BD y luego de ejecutar el método guardarForm, se muestra el segundo mensaje que predeterminé para cuando ocurra un problema al intentar guardar los datos.

Ambos métodos invocan a dos procedimientos almacenados cada uno, que, realiza una consulta en la BD y guarda los datos, respectivamente. He probado colocando queries sencillas como INSERT INTO... o SELECT * FROM..., pero el resultado es exactamente el mismo, incluso probé invocando a otro método, como paises para mostrar la lista de países en la BD, pero tampoco funciona, sin embargo, he probado creando una nueva instancia tanto para la conexión a la BD como para la clase de consultas antes de invocar a los dos métodos restantes (email y guardarForm) y de este modo sí funciona:
Código PHP:
Ver original
  1. <?php
  2. //E-Mail
  3. $email = (strlen($_POST["email"]) && isset($_POST["email"]) && !is_null($_POST["email"])) ? $scripts->validarEMail($desinfectar->sanitize($miConexion->conexion, $_POST["email"])) : $scripts->formulario();
  4. if (is_null($email))
  5.     $scripts->formulario("Debe de ingresar su E-Mail en un formato válido");
  6. else {
  7.     $miConexion2 = new Cls_Conexion();
  8.     $miConsulta2 = new Cls_Consultas($miConexion2->conexion);
  9.  
  10.     $verificarEmail = $miConsulta2->email($email);
  11.     if ($verificarEmail->num_rows) {
  12.         $scripts->formulario("El E-Mail ingresado se encuentra registrado. Por favor, ingrese otro.");
  13.         $email = NULL;
  14.         $verificarEmail->free();
  15.     }
  16. }
  17.  
  18. //Aquí va el resto del código hasta antes del guardado de datos
  19.  
  20. if ($bandera) {
  21.     $miConexion3 = new Cls_Conexion();
  22.     $miConsulta3 = new Cls_Consultas($miConexion3->conexion);
  23.  
  24.     //Guardamos los datos del formulario en la Base de datos
  25.     if ($miConsulta3->guardarForm($datos))
  26.         echo "Los datos han sido guardados satisfactoriamente";
  27.     else
  28.         echo "Ha ocurrido un error al intentar guardar los datos";
  29. }
  30. ?>

Instancias a ambas clases antes de cada llamada a los métodos, todo marcha bien, incluso el método email muestra el mensaje de advertencia cuando se ingresa un email existente.

Mi pregunta es, ¿por qué tengo que instanciar dos veces a los métodos de conexión y consultas para que todo marche bien?

Saludos y, de antemano, gracias por la deferencia.

P.D.: El enlace que puse al inicio, los redirigirá al hilo que publiqué hace unas semanas sobre este tema, ahí podrán tener más detalles del código, aunque el problema se centra en lo que muestre en éste.