Foro oficial de PHP

Hola amigos del foro, mi problema es el siguiente:

Estoy por terminar de hacer una pequeña aplicación en PHP, la cual guarda en una BD los datos ingresados en un formulario, para que este proceso sea seguro, valido los datos del lado del cliente con HTML5 y jQuery y del lado del servidor con PHP, en todos los casos siempre usando expresiones regulares, además, manejo con clases tanto a la conexión a la BD como las llamadas a las funciones que invocan a los procedimientos almacenados, es decir, hago uso de la POO.

Mi conexión la realizado de esta forma:
PHP:
<?php
class Cls_Conexion {
    public $conexion;

    public 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();
    }
}
?>

La clase que contiene los métodos que llaman a los procedimientos almacenados (de ahora en adelante PA), es la siguiente:
PHP:
<?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"]
            ));
    }
}
?>

Y el archivo que recibe los datos del formulario e invoca a los métodos de la clase que llaman a los PA es esta:
PHP:
<?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();
if (is_null($email))
    $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
$datos = array(
            "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)
    if (is_null($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";
?>

Al parecer, después de la llamada al método codigo, la cual devuelve el resultado esperado, la variable $miConsulta que es la que representa a la clase en el archivo de procesos (el tercero), deja de funcionar, probé imprimiendo mensajes si es que se obtenía un resultado y la respuesta siempre fue negativa, por ejemplo en: echo $miConsulta->email($email) ? "TRUE" : "FALSE"; siempre se imprimía "FALSE", cuando utilizo la función mysqli_errno(), se muestra el código de error 2014 de descripción"Commands out of sync; you can't run this command now", incluso intenté hacer esto:
PHP:
<?php
$paises = $miConsulta->paises();
while ($row = $paises->fetch_array())
    echo $row["nombre"] . "<br />";
?>

Se muestra el siguiente mensaje: "Fatal error: Call to a member function fetch_array() on a non-object in line 30", dicha línea es en donde se encuentra el ciclo While.

Como verán en el código, son 3 llamadas a 3 métodos de la clase, la primera llamara al método codigo, la segunda al método email y la tercera al método guardarForm, de las cuales, solamente la primera llamada me retorna el valor esperado, mientras que las otras dos no funcionan, sin embargo, si inhabilito a la primera llamada, es decir, a la del código, funciona la del email pero no la de guardarForm y recién cuando deshabilito la del email, funciona la de guardarForm. Otra forma en que funciona esto es creando una nueva instancia para la conexión y para la clase de esta forma:
PHP:
<?php
//E-Mail
$email = (strlen($_POST["email"]) && isset($_POST["email"]) && !is_null($_POST["email"])) ? $scripts->validarEMail($desinfectar->sanitize($miConexion->conexion, $_POST["email"])) : $scripts->formulario();
if (is_null($email))
    $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, no lo volví a poner porque no es necesario

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";
}
?>

Del modo mostrado arriba, funciona todo sin necesidad de inhabilitar ninguna llamada. Probé utilizando queries sencillas en lugar de procedimientos almacenados, pero el resultado es el mismo, con lo que todo apunta a que el problema radica en lo que les he explicado.

Cabe señalar que los métodos paises y ciudades, funcionan pues las llamadas que hago para cada uno de esos métodos, las realizo en diferentes archivos, instanciando en cada uno a la conexión y a la clase.

Ahora, mi pregunta es: ¿Por qué solamente puedo utilizar una vez a la variable que instancia a la clase con los métodos y solamente inhabilitando todas menos una, ésta que no es deshabilitada logra funcionar y por qué creando otras instancias para la clase, recién logran funcionar las tres llamadas a los métodos?

Saludos y, de antemano, gracias por su deferencia.
 
Gente una pregunta.....alguien conoce algun framework de php que principalmente sea facil que me permita cosas muy basicas (crear formularios, mostrar informacion de tablas y gestion de usuarios)

Gracias :)
 
Hola a todos, aqui voy con mi pregunta, soy principiante en php asi q tenganme paciencia por favor :)
bien, tengo una clase llamada Diagnostico la cual tiene un metodo setIdEstudio(Estudio $isEstudio=null)
necesito enviar un valor a este metodo el cual lo obtengo asi: $valor=$_POST["estudio"]; (esto viene de un select llamado estudio)
si hago:
PHP:
$entity = new Diagnostico();
$entity->setIdEstudio($valor);
da un error de que debo enviar una instancia de la clase Estudio, entonces hice esto:
PHP:
$objeto =new Estudio();
$objeto->$valor;
$entity->setIdEstudio($objeto);
Ahora dice que Notice: Undefined property:Estudio:$5 (ese 5 es el valor de la opcion q elegí en el select)
Alguna sugerencia??
 
Última edición:
Debes asignar $valor como una propiedad del estudio, mas o menos así (no se como tengas la parte de asignación):

$objeto = new Estudio();
$objeto->setPropiedad($valor); //hay que cambiar "Propiedad" por la propiedad real del objeto, ya sea id o valor, etc.
$entity->setIdEstudio($objeto);

Si estoy equivocado, por favor me corrigen...
 
Debes asignar $valor como una propiedad del estudio, mas o menos así (no se como tengas la parte de asignación):

$objeto = new Estudio();
$objeto->setPropiedad($valor); //hay que cambiar "Propiedad" por la propiedad real del objeto, ya sea id o valor, etc.
$entity->setIdEstudio($objeto);

Si estoy equivocado, por favor me corrigen...

Lo que pasa es q no quiero acceder a ninguna propiedad de la clase Estudio, sino de la clase Diagnostico.
 
La cuestión es que el método setIdEstudio de Diagnostico recibe un objeto de tipo Estudio. Entonces debes buscar la forma de que el objeto de tipo Estudio reciba el valor que le estas enviando y lo almacene en alguna de sus propiedades usando alguna función. Al hacerlo de la forma $objeto->$valor es como si estuvieras llamando a la variable que viene con el valor $valor (valga la redundancia) en el objeto Estudio.

Espero haberme hecho entender.
 
Que tal amigos ya he dejado de usar la funcion mysqli y sus derivados en favor de PDO por el tema de seguridad y la compatibilidad con varios drivers de bd, ahora al leer acerca de prepared statements y consultas parametrizadas, ¿ya con estos ejemplos que pongo debajo estoy evitando sql injection? ¿asi de simple sin mas nada? gracias por su ayuda desde ya.

PHP:
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

$stmt->execute(array('name' => $name));

foreach ($stmt as $row) {
    // do something with $row
}
-----------------------------------------------------------------------------
PHP:
$sql = 'SELECT emailaddress FROM users WHERE username = ? AND password = ?';
$query = $db->prepare($sql);
$query->bindParam(1, $_REQUEST['username']);
$query->bindParam(2, $_REQUEST['password']);
 
Que tal amigos ya he dejado de usar la funcion mysqli y sus derivados en favor de PDO por el tema de seguridad y la compatibilidad con varios drivers de bd, ahora al leer acerca de prepared statements y consultas parametrizadas, ¿ya con estos ejemplos que pongo debajo estoy evitando sql injection? ¿asi de simple sin mas nada? gracias por su ayuda desde ya.

PHP:
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

$stmt->execute(array('name' => $name));

foreach ($stmt as $row) {
    // do something with $row
}
-----------------------------------------------------------------------------
PHP:
$sql = 'SELECT emailaddress FROM users WHERE username = ? AND password = ?';
$query = $db->prepare($sql);
$query->bindParam(1, $_REQUEST['username']);
$query->bindParam(2, $_REQUEST['password']);

Nunca sobra hacer uso de funciones tales como htmlspecialchars(), ademas recuerde que el SQL Injection no se hace unicamente por medio de peticiones POST o GET, actualmente tambien se puede hacer por medio de web services, JSON o por ataques directos al APACHE o servidor correspondiente.

Imaginese que usted por algun motivo tiene un script en php que recibe parametros desde un webservice externo y lo procesa por medio de un json_decode para posteriormente llevar a cabo sentencias SQL. Imaginese que pasaria si por ejemplo alguien curioso descubre en el codigo de su pagina la url desde la cual se llama el webservice, la edita y la cambia por un json cualquiera hecho por este sujeto el cual tenga sentencias SQL y cumpla con los keys necesarios para que su codigo pueda leerlo.

La cuestión es que el método setIdEstudio de Diagnostico recibe un objeto de tipo Estudio. Entonces debes buscar la forma de que el objeto de tipo Estudio reciba el valor que le estas enviando y lo almacene en alguna de sus propiedades usando alguna función. Al hacerlo de la forma $objeto->$valor es como si estuvieras llamando a la variable que viene con el valor $valor (valga la redundancia) en el objeto Estudio.

Espero haberme hecho entender.

Espero haberle entendido bien pero en esos casos lo mejor y mas practico es hacer uso de un setter, al tener instanciado un objeto y llamar un setter dentro del objeto vamos a tener que el cambio que se haga va a perdurar en el objeto creado hasta que este desaparezca


Yo tengo una pregunta: Actualmente hay alguna forma de que un codigo php ejecute una serie de funciones como un multithread con el fin de mejorar el rendimiento de la aplicacion? Por ejemplo si tengo un objeto DAO que por medio de una configuracion tiene que hacer una misma sentencia a 10 servidores distintos que usen digamos MySQL y se encuentren en otros puntos geograficos, no hay una forma de que se ejecuten las 10 sentencias como un multithread en vez de ejecutar una por una?
 
Última edición:
Nunca sobra hacer uso de funciones tales como htmlspecialchars(), ademas recuerde que el SQL Injection no se hace unicamente por medio de peticiones POST o GET, actualmente tambien se puede hacer por medio de web services, JSON o por ataques directos al APACHE o servidor correspondiente.

Imaginese que usted por algun motivo tiene un script en php que recibe parametros desde un webservice externo y lo procesa por medio de un json_decode para posteriormente llevar a cabo sentencias SQL. Imaginese que pasaria si por ejemplo alguien curioso descubre en el codigo de su pagina la url desde la cual se llama el webservice, la edita y la cambia por un json cualquiera hecho por este sujeto el cual tenga sentencias SQL y cumpla con los keys necesarios para que su codigo pueda leerlo.

Le entiendo perfectamente la segunda parte de su respuesta, pero hablando de un caso puntual de formularios en una aplicacion se puede decir un poco mas "controlada" los cuales tienen validación de los datos tanto en el front-end (http://validity.thatscaptaintoyou.com/) como en el server-side con php, y como dije casos puntuales de formularios del estilo siguiente:

PHP:
$sql = "INSERT INTO clientes VALUES (NULL,:iduser,:nombre,:cedula,:dir,:tel)";
$query = $db->prepare($sql);
$query->execute(array(
    ':iduser'=>($_POST['id']),
    ':nombre'=>($_POST['nombre']),
    ':cedula'=>($_POST['cedula']),
    ':dir'=>($_POST['dir']),
    ':tel'=>($_POST['tel']),
                    ))

Usando este código estaría evitando SQL Injection usando PDO para ese formulario?
 
Le entiendo perfectamente la segunda parte de su respuesta, pero hablando de un caso puntual de formularios en una aplicacion se puede decir un poco mas "controlada" los cuales tienen validación de los datos tanto en el front-end (http://validity.thatscaptaintoyou.com/) como en el server-side con php, y como dije casos puntuales de formularios del estilo siguiente:

PHP:
$sql = "INSERT INTO clientes VALUES (NULL,:iduser,:nombre,:cedula,:dir,:tel)";
$query = $db->prepare($sql);
$query->execute(array(
    ':iduser'=>($_POST['id']),
    ':nombre'=>($_POST['nombre']),
    ':cedula'=>($_POST['cedula']),
    ':dir'=>($_POST['dir']),
    ':tel'=>($_POST['tel']),
                    ))

Usando este código estaría evitando SQL Injection usando PDO para ese formulario?

Yo creo que si estaria reduciendo las posibilidades de un SQL injection aunque me queda la duda sobre como se comportaria el PDO ante la inserción de codigo malicioso en los campos tipo String
 
hola, estoy empezando a aprender php ahora tengo una pregunta ya he googleado pero nada, tengo una consulta a una base de datos de mysql a través de un formulario la porción de código es
$consulta= "SELECT * FROM correos WHERE
nombre LIKE '".$_POST['buscar']."' todo funciona bien pero no entiendo para que sirven el punto que esta antes de $ y despues de ] buscar lo estoy obteniendo de un formulario html a traves de post, gracias
 
hola, estoy empezando a aprender php ahora tengo una pregunta ya he googleado pero nada, tengo una consulta a una base de datos de mysql a través de un formulario la porción de código es
$consulta= "SELECT * FROM correos WHERE
nombre LIKE '".$_POST['buscar']."' todo funciona bien pero no entiendo para que sirven el punto que esta antes de $ y despues de ] buscar lo estoy obteniendo de un formulario html a traves de post, gracias
Mucho cuidado con una inyeccion SQL, uno nunca puede confiar en lo que los usuarios escriben. Consule un poco acerca del "input sanitize".

Respecto a su inquietud, el punto sirve para concatenar cadenas, algo asi como "a"."b" = "ab".
 
gracias por la respuesta, pero lo que no entiendo es para que sirven eso puntos en la porción de código que dejé, ya que no veo que estén concatenando nada
 
gracias por la respuesta, pero lo que no entiendo es para que sirven eso puntos en la porción de código que dejé, ya que no veo que estén concatenando nada
Como le dije, concatenan la cadena "SELECT * FROM correos WHERE nombre LIKE" con el contenido de la variable "buscar" recibida mediante método POST.
 
gracias por la respuesta, pero lo que no entiendo es para que sirven eso puntos en la porción de código que dejé, ya que no veo que estén concatenando nada

Permite diferenciar una cadena de una variable conservando su unión.

Ejemplo
PHP:
<?php
$numero = 4;
echo "Yo tengo ".$numero."20 casas.";
?>

Si estas empezando te recomiendo empieces de una vez con PDO se que es un poco mas serio al entender como funciona pero es mucho mas seguro. no uses tus variables POST o GET directamente en la sentencia SQL puedes sufrir una SQL Injection
 
ufffffff, gracias KrLx esa era justo la respuesta que necesitaba, ahora si me quedo clarísimo, me disculpan mi ignorancia, hasta ahora empiezo con php así que estaré por aquí molestando de vez en cuando
 
Permite diferenciar una cadena de una variable conservando su unión.

Ejemplo
PHP:
<?php
$numero = 4;
echo "Yo tengo ".$numero."20 casas.";
?>

Si estas empezando te recomiendo empieces de una vez con PDO se que es un poco mas serio al entender como funciona pero es mucho mas seguro. no uses tus variables POST o GET directamente en la sentencia SQL puedes sufrir una SQL Injection
Si ojo con el sql inyection recuerdo cuando estaba aprendiendo tenía una página como con 1000 usuarios, y de un momento a otro tenía la tabla de usuarios vacía Jajajjaa

Enviado desde mi LG-D805 mediante Tapatalk
 
Compañeros, me podrían recomendar una página donde muestren paso a paso cómo hacer un importador sencillo? que me permita subir un archivo de texto y mostrarlo en una tabla por ejm.
 

Los últimos temas