1

Tengo un error en la siguiente función pero no encuentro dónde:

   static public function obtenerCabanasPorFecha($fi, $ff){
        //Realizamos la consulta.
        $ejecucion = self::Conexion();
        $registro = $ejecucion->query("SELECT c.* FROM cabanas AS c WHERE c.idcabana NOT IN (SELECT idcabana FROM reservas WHERE ('$fi' >= check_in OR '$ff' >= check_out) AND ('$ff' <= check_in OR '$fi' <= check_out));");
        //Creamos un array de cabanas.
        $cabanas = array();
        //Mientras haya datos los guardamos...
        while($datos = $registro->fetch()){
            $datos["imagenes"] = BD::obtenerImagenesCabana($datos["idcabana"]);
            $micabana = new Cabanas($datos);
            //array_push: añadir un elemento al final de un array.
            array_push($cabanas, $micabana);
        }
        return $cabanas;
    }

Incluyo la función obtenerImagenesCabana:

static public function obtenerImagenesCabana($idcabana){
        //Realizamos la consulta.
        $ejecucion = self::Conexion();
        $sql = "SELECT ruta FROM imagenes WHERE idcabana=$idcabana";
        $registro = $ejecucion->query($sql);
        //Creamos una array de imagenes.
        $imagenes = array();
        //Mientras haya datos los guardamos...
        while($datos = $registro->fetch()){
            //Array asociativo: al array $imagenes le pasamos la imagen concreta.
            array_push($imagenes, $datos["ruta"]);
        }
        //Devolvemos el array de imagenes.
        return $imagenes;
    }

Error:

Fatal error: Call to a member function fetch() on a non-object in /hosting/distancia/www/Clases/BD.php on line 207

Tablas en BBDD:

introducir la descripción de la imagen aquí

omaza1990
  • 2,722
  • 32
  • 82
  • 143
  • 1
    ¿El `fetch` que falla es el del `obtenerImagenesCabana`? Si es así ¿Has validado que `$idcabana` se este pasando? Ejemplo: `$sql = "SELECT ruta FROM imagenes WHERE idcabana=$idcabana"; die($sql);` – Marcos Jan 10 '18 at 22:19
  • Probablemente el resultado de la sentencia te está regresando un objeto vacío, por lo que así no te permite ejecutar la función, una vez que valides el resultado de tu sentencia intenta también mandar como parámetro a la función `fetch` `PDO::FETCH_ASSOC` – Yikarus Jan 10 '18 at 22:20
  • @Marcos El fetch que falla es el de la primera funcion, obtenerCabanasPorFecha. – omaza1990 Jan 10 '18 at 22:25

1 Answers1

2

El problema

Fatal error: Call to a member function fetch() on a non-object suele ocurrir cuando la consulta por algún motivo ha sido errónea. De haber funcionado la consulta tendrías un objeto desde el cual podrías llamar al método fetch, pero al fallar lo que tienes es una variable booleana con valor false, la cual no es un objeto que posea un método fetch.

La solución

Creo que hay que ser agnósticos a la hora de usar nuestras variables, ellas pueden fallar y nosotros debemos controlar esos fallos.

En este caso conviene evaluar el resultado de la consulta antes operar con un posible conjunto de resultados.

Propongo esta solución, donde controlaremos tanto la conexión como la consulta que envías.

   static public function obtenerCabanasPorFecha($fi, $ff){
        /*Realizamos la consulta.*/
        $ejecucion = self::Conexion();
        $arrResultado=array();
        if ($ejecucion){
            $strSQL="SELECT c.* FROM cabanas AS c WHERE c.idcabana NOT IN (SELECT idcabana FROM reservas WHERE ('$fi' >= check_in OR '$ff' >= check_out) AND ('$ff' <= check_in OR '$fi' <= check_out))";
            $registro = $ejecucion->query($strSQL);
            if ($registro){
                /*
                   *Creamos un array de cabanas.
                   *Mientras haya datos los guardamos...
                */
                while($datos = $registro->fetch(PDO::FETCH_ASSOC)){
                    $datos["imagenes"] = BD::obtenerImagenesCabana($datos["idcabana"]);
                    $micabana = new Cabanas($datos);
                    /*array_push: añadir un elemento al final de un array.*/
                    array_push($arrResultado, $micabana);
                }

            }else{
                $arrResultado["error"]=$ejecucion->errorInfo()[2];    
            }
        }else{
                $arrResultado["error"]=$ejecucion->errorInfo()[2];            
        }
        return $arrResultado;
    }

P.D.:

  1. Viendo que desde la función tú llamas a otra función dentro del while para en cada llamada ejecutar una consulta a la base de datos, en tu caso me plantearía traer todos los datos que necesito en una sola consulta.

  2. La consulta que estás ejecutando es vulnerable a la Inyección SQL. Pasar valores de variables en consultas directamente es una puerta grande a la Inyección de código, la cual puede afectar no solamente a tu base de datos, sino a otras áreas de tu sistema. Consultar al respecto: ¿La Inyección SQL actúa sólo a nivel de la base de datos o el riesgo es aún mayor?

A. Cedano
  • 86,578
  • 19
  • 122
  • 221