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<?php
//Incluimos el archivo de conexión a la Base de datos y nos conectamos
include("conexion.php");
$miConexion = new Cls_Conexion();
//Incluimos el archivo de seguridad de datos
include("seguridad.php");
$desinfectar = new Cls_Desinfeccion();
//Incluimos el archivo de consultas a la Base de datos
include("consultas.php");
$miConsulta = new Cls_Consultas($miConexion->conexion);
//Incluimos el archivo de scripts PHP
include("scripts.php");
$scripts = new Cls_Scripts();
//Código
$codigo = $scripts->codigo();
$verificarCodigo = $miConsulta->codigo($codigo);
if ($verificarCodigo->num_rows) {
do {
$codigo = $scripts->codigo();
$verificarCodigo = $miConsulta->codigo($codigo);
} while ($verificarCodigo = $miConsulta->codigo($codigo));
$verificarCodigo->free();
}
//Nombre
$nombre = (strlen($_POST["nombre"]) && isset($_POST["nombre"]) && !is_null($_POST["nombre"])) ?
$scripts->validarNomApe($desinfectar->sanitize($miConexion->conexion, $_POST["nombre"])) : $scripts->formulario(); if (is_null($nombre)) $scripts->formulario("Debe de ingresar su nombre en un formato válido");
//Apellidos
$apellidos = (strlen($_POST["apellidos"]) && isset($_POST["apellidos"]) && !is_null($_POST["apellidos"])) ?
$scripts->validarNomApe($desinfectar->sanitize($miConexion->conexion, $_POST["apellidos"])) : $scripts->formulario(); if (is_null($apellidos)) $scripts->formulario("Debe de ingresar sus apellidos en un formato válido");
//E-Mail
$email = (strlen($_POST["email"]) && isset($_POST["email"]) && !is_null($_POST["email"])) ?
$scripts->validarEMail($desinfectar->sanitize($miConexion->conexion, $_POST["email"])) : $scripts->formulario(); $scripts->formulario("Debe de ingresar su E-Mail en un formato válido");
else {
$verificarEmail = $miConsulta->email($email);
if ($verificarEmail->num_rows) {
$scripts->formulario("El E-Mail ingresado se encuentra registrado. Por favor, ingrese otro.");
$email = NULL;
$verificarEmail->free();
}
}
//Domicilio
$domicilio = (strlen($_POST["domicilio"]) && isset($_POST["domicilio"]) && !is_null($_POST["domicilio"])) ?
$scripts->validarDomicilio($desinfectar->sanitize($miConexion->conexion, $_POST["domicilio"])) : $scripts->formulario(); if (is_null($domicilio)) $scripts->formulario("Debe de ingresar su dirección domiciliaria en un formato válido y utilizando menos de 256 caracteres");
//Fecha de nacimiento
$fechanac = (strlen($_POST["fechanac"]) && isset($_POST["fechanac"]) && !is_null($_POST["fechanac"])) ?
$scripts->validarFechNac($desinfectar->sanitize($miConexion->conexion, $_POST["fechanac"])) : $scripts->formulario(); if (is_null($fechanac)) $scripts->formulario("Debe de ingresar la fecha de su nacimiento en un formato válido");
//País
$pais = (strlen($_POST["pais"]) && isset($_POST["pais"]) && !is_null($_POST["pais"])) ?
$scripts->validarPaisCiudad($desinfectar->sanitize($miConexion->conexion, $_POST["pais"])) : $scripts->formulario(); if (is_null($pais)) $scripts->formulario("Debe de elegir un país de la lista");
//Ciudad
$ciudad = (strlen($_POST["ciudad"]) && isset($_POST["ciudad"]) && !is_null($_POST["ciudad"])) ?
$scripts->validarPaisCiudad($desinfectar->sanitize($miConexion->conexion, $_POST["ciudad"])) : $scripts->formulario(); if (is_null($ciudad)) $scripts->formulario("Debe de elegir una ciudad de la lista");
//Añadimos todos los datos a un array que será enviado a la función de procesamiento de datos
"codigo" => $codigo,
"nombre" => $nombre,
"apellidos" => $apellidos,
"email" => $email,
"domicilio" => $domicilio,
"fechanac" => $fechanac,
"pais" => $pais,
"ciudad" => $ciudad
);
$bandera = true; //Comodín para determinar si se guardarán o no los datos
foreach ($datos as $dato)
$bandera = false;
break;
}
if ($bandera)
//Guardamos los datos del formulario en la Base de datos
if ($miConsulta->guardarForm($datos))
echo "Los datos han sido guardados satisfactoriamente";
else
echo "Ha ocurrido un error al intentar guardar los datos";
?>
La conexión la realizo de esta forma:
Código PHP:
Ver original<?php
class Cls_Conexion {
public $conexion;
function __construct() {
//Conexión a la base de datos
$servidor = "localhost"; //Nombre del servidor
$usuario = "root"; //Nombre de usuario en tu servidor
$password = "miclave"; //Contraseña del usuario
$base = "bd_formulario"; //Nombre de la Base de Datos
//Se realiza la conexión
return $this->conexion = new mysqli
($servidor, $usuario, $password, $base) or
exit("Se ha producido un error en la conexión al servidor"); }
function __destruct() {
$this->conexion->close();
}
}
?>
Y la clase que contiene los métodos que realizan consultas a la BD es el siguiente:
Código PHP:
Ver original<?php
class Cls_Consultas {
public $conexion;
function __construct($conex) {
$this->conexion = $conex;
}
function paises() {
return $this->conexion->query("CALL USP_listCountries()");
}
function ciudades($pais) {
return $this->conexion->query(sprintf("CALL USP_listCities(%d)", $pais)); }
function codigo($codigo) {
return $this->conexion->query(sprintf("CALL USP_validateCode('%s')", $codigo)); }
function email($email) {
return $this->conexion->query(sprintf("CALL USP_validateEmail('%s')", $email)); }
function guardarForm($datos) {
return $this->conexion->query(sprintf("CALL USP_saveForm('%s', '%s', '%s', '%s', '%s', '%s', %d, %d)", $datos["codigo"],
$datos["nombre"],
$datos["apellidos"],
$datos["email"],
$datos["domicilio"],
$datos["fechanac"],
$datos["pais"],
$datos["ciudad"]
));
}
}
?>
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<?php
//E-Mail
$email = (strlen($_POST["email"]) && isset($_POST["email"]) && !is_null($_POST["email"])) ?
$scripts->validarEMail($desinfectar->sanitize($miConexion->conexion, $_POST["email"])) : $scripts->formulario(); $scripts->formulario("Debe de ingresar su E-Mail en un formato válido");
else {
$miConexion2 = new Cls_Conexion();
$miConsulta2 = new Cls_Consultas($miConexion2->conexion);
$verificarEmail = $miConsulta2->email($email);
if ($verificarEmail->num_rows) {
$scripts->formulario("El E-Mail ingresado se encuentra registrado. Por favor, ingrese otro.");
$email = NULL;
$verificarEmail->free();
}
}
//Aquí va el resto del código hasta antes del guardado de datos
if ($bandera) {
$miConexion3 = new Cls_Conexion();
$miConsulta3 = new Cls_Consultas($miConexion3->conexion);
//Guardamos los datos del formulario en la Base de datos
if ($miConsulta3->guardarForm($datos))
echo "Los datos han sido guardados satisfactoriamente";
else
echo "Ha ocurrido un error al intentar guardar los datos";
}
?>
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.