0

compañer@s.

He creado un sitio web con vue y como back, con PHP. Comprobé que todo estuviera bien antes de subirlo al servidor y entonces lo hice. Cuando ya estaba en internet, me di cuenta que las consultas que traían varios registros, me devolvía falso, pero los que devuelven un único registro, funciona perfecto.

He durado días haciendo pruebas y he notado que el json_encode me devuelve false (comprobado con var_dump), pero sin esta función, me devuelve todos los datos como deben ser (sin formato json, claro).

Nota: Utilizo MVC (la V es Vue), PDO y POO.

Esta es la conexión:

<?php

class conexion {
    
    private $host = "localhost";
    private $db_name = "bd_name";
    private $user = "root";
    private $pass = "pass";

    private static $conexion = null;
    private $conn;

    private function __construct() {

        try {

            $this->conn = new PDO("mysql:host=$this->host;dbname=$this->db_name", $this->user, $this->pass);

        } catch (PDOException $e) {

            echo "Error: " . $e;

        }

    }

    public static function obtenerInstancia() {

        if(!self::$conexion) {

            self::$conexion = new Conexion();

        }

        return self::$conexion;

    }

    public function getPrepareStatement($sql) {

        return $this->conn->prepare($sql);

    }

    public function getFetch($PreparedStatement, $option) {

        $PreparedStatement->setFetchMode(PDO::FETCH_ASSOC);

        if ($PreparedStatement->execute()) {
            
            return !$option ? $PreparedStatement->fetch() : $PreparedStatement->fetchAll();

        }else {

            return $PreparedStatement->errorInfo();

        }

    }
    
}

Así recibo el dato que envía vue (a través de axios) para inicializar la clase:

<?php

header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
header('Content-type: application/json');

require_once '../controlador/controladorResultados.php';

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    
    $_POST = json_decode(file_get_contents("php://input"), true);

    extract($_POST);

    $controlador = new controladorResultados();

    if (isset($_POST['consultarRedes']) && !empty($_POST['consultarRedes']) && $consultarRedes == true) {
        
        print_r($controlador->consultarRedesConocimiento());

    }

}

Esta es la clase:

<?php

header('Content-type: application/json');

require_once 'capsulas/proyectos.php';

require_once '../modelo/modeloResultados.php';

require_once 'controladorValidacion.php';

/**
 * Clase que controla los datos de los resultados de investigación.
 */
class controladorResultados extends controladorValidacion {

    private $modelo;
    
    public function __construct() {
        
        $this->modelo = new modeloResultados();

    }

    public function consultarRedesConocimiento() {

        //Esto es lo que me devuelve falso. Sin el json_encode, en el servidor, me devuelve lo datos, pero no me sirve el formato de PHP.
        return json_encode($this->modelo->consultarRedesConocimientoBD("redes_conocimiento"), JSON_UNESCAPED_UNICODE);

    }

}

Y este es el modelo y cómo traigo la consulta:

<?php

require_once 'conexion.php';

/**
 * Clase que conecta con la base de datos.
 */
class modeloResultados {

    private $conexion;
    
    public function __construct() {

        $this->conexion = conexion::obtenerInstancia();

    }

    public function consultarRedesConocimientoBD($tabla) {
        
        $sql = "SELECT * FROM $tabla";  

        try {

            $PreparedStatement = $this->conexion->getPrepareStatement($sql);

            return $this->conexion->getFetch($PreparedStatement, true);
            
        } catch (PDOException $e) {
            
            return "Error: " . $e;

        }

    }

}

Adjunto imagen de un console.log(response.data), cuando retorno un var_dump() sin json_encode().

introducir la descripción de la imagen aquí

Esto es sólo un ejemplo, pero ninguna consulta que traiga más de 2 registros, me funciona, pero los que son de registro único, sí me los trae.

¿Cómo puedo resolver esto, o si alguien me puede decir que este es problema del servidor?

Saco04
  • 621
  • 5
  • 18
  • No entiendo bien lo que dices al final. ¿Quisiste decir que en el caso de varias filas el `var_dump()` muestra datos, pero que sin embargo el json no se crea? Haz una prueba sencilla, con sólo dos filas y muéstranos el resultado del `var_dump()` pulsando en [edit]. Para ir mejorando tu código, te comento que estás aplicando `setFetchMode()` dos veces, con que lo apliques en el método `getFetch()` bastaría, o mejor aún, lo puedes indicar en la conexión y donde necesites otro tipo de fetch lo indicas explícitamente in situ con `setFetchMode()`. – A. Cedano Nov 13 '20 at 17:12
  • Digo que, en el caso de más de 1 fila, el var_dump() sí muestra la cosnulta que es, pero el json_encode devuelve falso. – Saco04 Nov 13 '20 at 18:03
  • Y lo del fetchMode ya lo modifiqué. No me había dado cuenta, pero ese no es el problema. – Saco04 Nov 13 '20 at 18:03
  • Ya sé que ese no es el problema, te lo señalé para que vayas optimizando el código. Te sugerí algo para ayudarte a encontrar el problema: Haz una prueba con dos filas (ponle un `LIMIT 2` a la consulta) y muéstranos el `var_dump` que sale para ver por qué no valida el json. – A. Cedano Nov 13 '20 at 18:04
  • Ya he actualizado la pregunta con una captura de lo que me muestra. Y ya corregí el doble setFetchMode(). – Saco04 Nov 13 '20 at 18:10
  • En el segundo resultado hay un carácter inspector que rompería el JSON, por eso `json_encode` te está devolviendo `false` . Tienes que aplicar codificación `utf-8` en todo tu entorno: HTML, PHP, conexión a PDO y en la base de datos, si ese dato estuviese así en la misma. Debes revisar punto por punto, empezando por el HTML. Revisa [lo explicado aquí](https://es.stackoverflow.com/a/59510/29967), pues tienes ese problema en tus datos. – A. Cedano Nov 13 '20 at 18:16
  • Ok... Buah... Vue por defecto venía con UTF-8. PHP, lo puse igual. ¿Cómo hago para hacerlo en PDO y en la base de datos (que la tengo en latin1_swedish_ci)? Porque ya hice la prueba y sí me lo puso con 2 datos. – Saco04 Nov 13 '20 at 18:23
  • En PDO puedes pasar un valor para el charset en el DSN, o puedes hacerlo con `SET NAMES` como explico en la respuesta enlazada en mi anterior comentario (*punto 3*, donde dice: ***En el caso de PDO***). En cuanto a la BD tendrías que ejecutar un ALTER TABLE para cambiarlo, pero OJO con eso, antes de cambiarlo deberías hacer un backup de tus tablas. Si maneja datos en castellano (que tendrán acentos, `ñ` y otros), es mejor usar `utf8_spanish_ci`. – A. Cedano Nov 13 '20 at 18:28
  • Para el PDO, ¿Me sirve así?: `$this->conn = new PDO("mysql:host=$this->host;dbname=$this->db_name", $this->user, $this->pass, $this->opciones);`, – Saco04 Nov 13 '20 at 18:31
  • Siendo `private $opciones = array( PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'" );` – Saco04 Nov 13 '20 at 18:32
  • ¿Y me tocaría actualizar todas las tablas de la base de datos? – Saco04 Nov 13 '20 at 18:37
  • Sí, para la conexión con eso debería bastar. Prueba cambiando eso en la conexión y revisa si el carácter inspector desaparece del dato. Si no desaparece, entonces verifica que el cliente y PHP tienen utf-8 y si lo tienen, entonces revisa los datos directamente en la BD. Si allí esa columna tiene el carácter inspector, significa que tendrás que arreglar los datos allí porque se insertaron mal. Si eso ocurrió y sigues insertando datos de alguna fuente externa, debes revisar tu código de inserción, la condificación de esas fuentes, etc (es lo que explico del *Nivel 0* en la respuesta). – A. Cedano Nov 13 '20 at 18:40
  • OJO: el que los datos salgan mal aquí no significa que necesariamente estén mal en la BD, puede ser un problema de la codificación aquí, en este contexto, por eso insisto en la respuesta sobre ir por niveles, para que no te vayas a modificar datos a lo loco en la base de datos. Dicho eso, aunque los datos estén bien en la BD (sin caracteres raros), para manejar información en castellano es mejor dar a la BD una collation en castellano (esto influye por ejemplo cuando hay que ordenar datos, no es sólo que puedas tener caracteres raros), pero antes de aplicar collation, haz backup de los datos. – A. Cedano Nov 13 '20 at 18:43
  • Amigo, muchísimas gracias. Nunca pensé que era un problema de cotejamiento. De verdad te agradezco. – Saco04 Nov 13 '20 at 18:58
  • De nada, me alegro de haberte ayudado. Saludos. – A. Cedano Nov 13 '20 at 18:58

0 Answers0