Peticiones AJAX que devuelven error JSON

oFF-sIDE

Hola.

Tengo un problema con unas peticiones AJAX. Es muy raro y por eso requiero de vuestra iluminación.

He hecho una aplicación web con un framework Javascript. Mediante peticiones AJAX a distintas funciones PHP, carga los modelos de datos de la aplicación. Mientras trabajé en local, no tuve problemas, pero ahora lo he subido a un servidor (hosting www.strato.es) y me encuentro con que las peticiones que devuelven MUY poca información sí funcionan, pero las peticiones que devuelven arrays de de objetos no funcionan para más de un objeto. El contenido de la base de datos es exactamente el mismo que el que había en la base de datos local. Básicamente porque he hecho un export/import de la base de datos local a la nueva.

Este es el resultado de una petición que devuelve un array de objetos:

Pero hay otra petición que también recupera un array, en este caso con 4 objetos de 8 atributos y me devuelve el siguiente error:

Entiendo que el error es de conversión JSON. Pero si esos mismos datos me funcionan en local, ¿por qué no funcionan el un servidor en internet?
Me he planteado que tal vez sea un problema en el tamaño de los datos, pero buscando información he leído que el único parámetro que puede afectar es el "post_max_size" de Apache. El caso es que el servidor donde lo tengo alojado permite hasta 48MB de datos en las peticiones, y aquí hablamos de texto plano en cantidades minúsculas.

El código que uso para las funciones AJAX es el siguiente:

peticionServidor: function(sUrl, oInput, fnCallbackOK, fnCallbackError) {
	$.ajax({
		type: "POST",
		url: "php/" + sUrl + ".php",
		data: oInput,
		dataType: "html",
		success: function(oData, sStatus, oRequest){
			if(fnCallbackOK) {
				fnCallbackOK(oData, sStatus, oRequest);
			}
		},
		error: function(oRequest, sStatus, sError){
			if(fnCallbackError !== undefined && fnCallbackError !== null) {
				fnCallbackError(oRequest, sStatus, sError);
			} else {
				SothisM.Mensajes.error("Error en la petición: "+sError);
				console.log("Error en la petición: %O", oRequest);
			}
			dlgCarga.close();
		}
	});
},

Ahí simplemente hago una llamada construyendo la petición y pasándole un objeto con los datos que quiero enviar.

He probado a hacerlo también con una petición GET, pero me pasa lo mismo.

¿Se os ocurre por donde pueden ir los tiros? No sé si puede ser algo de configuración del servidor, pero los de Strato se han desentendido totalmente y estoy bastante frustrado ya con esto.

Amazon

A ver el JSON que devuelve xD

oFF-sIDE

Vuelve de PHP con una función return. Devuelve un objeto con los datos dentro y ya te digo que con los mismos datos, en local funciona bien.

En PHP tengo lo siguiente:

//Variables de salida
$output = new stdClass();
$output->data = "";
$output->error = "";

$alumnos = array();

//Lectura de base de datos
....

$output->data = $alumnos;
$db_link->close();
return $output;

Voy a probar a quitar acentos y carácteres raros, a ver si es por enconding.

NoRelaX

Estás seguro de que te sigue devolviendo una cadena JSON?

oFF-sIDE

A mi a Javascript me llega un simple string que paso a JSON con la función

$.parseJSON(oData)
1 respuesta
NoRelaX

Mira a ver si en el String que recibes hay alguna comilla o algo que esté haciendo petar el parse. Con la info que has dado no se me ocurre otra cosa :s

oFF-sIDE

En las peticiones que recibo error no recibo el string, eso es lo peor de todo xD Y para poder ver el error he tenido que activar el log de errores con

error_reporting(E_ALL);
ini_set('display_errors', 1);
Amazon

Devuelves decimales? A lo mejor la configuración del server es distinta y en vez de 10.5 te devuelve 10,5 y el parser de JSON se flipa

oFF-sIDE

Sí, en algunos casos sí.

Acabo de darme cuenta de que hay errores en PHP que en el servidor local no me salían y que ahora, al poner las instrucciones:

error_reporting(E_ALL);
ini_set('display_errors', 1);

Sí me aparecen. Voy a depurar todo el código de toda la aplicación usando esas instrucciones porque seguro que por ahí deben ir los tiros. Os mantendré informados xD

NoRelaX

#5 No termino de entender del todo ni qué esperas obtener de servidor ni qué problema estás teniendo. Intuyo que ese código lo tienes en la función fnCallbackOK que no se va a invocar nunca porque la petición ajax termina en error, al no recibir un 200 del servidor.

Whatever. ¿Estás seguro de que dataType: "html" es correcto en la petición AJAX?

1 respuesta
oFF-sIDE

#10 A ver, me estoy aclarando un poco más. Con el "return" de PHP me está devolviendo un string plano que recibo en el callback de Javascript. Ese string lo parseo a JSON y ya tengo todos mis datos preparados para usar en Javascript.

AHORA me acabo de dar cuenta de que el problema es que estoy recibiendo una cadena vacía desde el servidor. Después, en Javascript, al hacer $.parseJSON da un error porque no puede parsear una cadena vacía por lo que escribe en consola el error: Uncaught SyntaxError: Unexpected end of JSON input. Y no, no tengo claro que HTML sea lo más correcto, pero es lo que vi cuando busqué por internet cómo hacer peticiones AJAX y como me funcionó a la primera no seguí buscando xD

Ahora el problema está más acotado. La pregunta es:
¿Por qué devuelve una cadena vacía si hay datos?

Voy a seguir indagando... Los datos son todos texto plano excepto una fecha. La fecha es tipo DATE, pero ya tengo en otras funciones tipos DATE y se devuelven correctamente.

1 respuesta
NoRelaX

#11 Es decir, ¿que el servidor está respondiendo la petición con un 'SUCCESS' pero en el oData te llega un blanco?

No estoy muy puesto en PHP... Pero mira a ver qué headers estás enviando en la request, que yo diría que por ahí van los tiros.
Tampoco veo muy claro que estés pidiendo los datos con una petición POST

1 respuesta
oFF-sIDE

#12 Exacto.

He preparado un caso concreto.

Tengo el siguiente objeto de salida:

$output->data = "";
$output->sql = SELECT * FROM alumnos WHERE IdTemporada='1' AND IdClub='1';
$output->error = "";

Si ejecuto esa SQL y meto en $output->data la cantidad de resultados que ha obtenido la SQL, a Javascript me llega todo correctamente. Pero si en $output->data meto el array de objetos me devuelve un simple vacío: ni objeto, ni sql, ni error. Simplemente vacío.

El resultado de la función AJAX devuelve 3 parámetros y así me llegan:
1º Datos: ""
2º Status: "success"
3º Response: objeto response con { readyState: 4, responseText: "", status: 200, statusText:"OK", ...}

Voy a investigar cómo funcionan los headers en las peticiones AJAX y lo pruebo xD

oFF-sIDE

YA ESTÁ CLARO EL ORIGEN: Son los acentos.

He quitado todos los acentos de una de las tablas y la petición que antes volvía vacía ahora funciona perfectamente.

El cotejamiento de todas las tablas y campos es utf8_spanish_ci. Lo raro es que en la base de datos pone:

Cotejamiento de la conexión al servidor: utf8mb4_spanish_ci 

y no me deja cambiarlo. ¿Pueden ir por ahí los tiros? Nunca había visto el utf8mb4

¿Alguna idea para saber si la culpa está en la lectura de base de datos o en la devolución de los datos desde PHP a Javascript?

1 respuesta
NoRelaX
#14oFF-sIDE:

¿Alguna idea para saber si la culpa está en la lectura de base de datos o en la devolución de los datos desde PHP a Javascript?

Si dices que te funcionaba hasta que cambiaste la BBDD de local a remota, diría que ahí tienes el problema.

oFF-sIDE

Voy a empezar por contactar con el servicio técnico de Strato para ver por qué leches no puedo cambiar de utf8mb4 a utf8 normal.

El caso es que he probado a hacer un encoding del dato obtenido de la base de datos

$nom = utf8_encode($fetch_element['Nombre']);

y a Javascript llega con los acentos codificados, pero el $.parseJSON ya me lo deja con acentos perfectos.

Misterio resuelto. Por mi podéis cerrar el thread. Gracias a los que os habéis interesado.

1
Amazon

mysql?

Qué usas para conectar a la base de datos? Le pones que vas a usar utf8?

1 respuesta
oFF-sIDE

#17 Sí, mySQL.

Para conectar JS con mySQL uso peticiones AJAX a funciones PHP. Mi base de datos local era utf8_spanish_ci y todas las tablas y campos igual. El caso es que la base de datos que tengo en internet es utf8mb_spanish_ci y no puedo ponerla en utf8_spanish_ci. Eso me obliga a hacer utf8_encode en los campos varchar. Me jode, pero como luego el $.parseJSON me lo deja bien, pues tira que te va.

No sé qué quieres decir con "Le pones que vas a usar utf8?"

1 respuesta
Amazon

#18 Después de conectar y seleccionar la base de datos

mysql_query("SET NAMES 'UTF8'");

Ó

$mysqli->set_charset("utf8");

De todos modos, no "conectas JS con mySQL", es PHP quien se conecta a la base de datos xD

1 2 respuestas
oFF-sIDE

#19 probaré lo del SET NAMES metiéndolo directamente en la clase mysql que uso. Si funciona me ahorro hacer los utf8_encode.

Respecto a conectar JS con MySQL... creo que está bastante claro a qué me refiero. Y si nos ponemos tontos, podemos hacer una relación transitiva en la que si A se relaciona con B y B se relaciona con C entonces A se relaciona con C (a través de B).

xDDDDDDD

1 respuesta
DaRk-eXe

#20 por mucho que te empeñes.. "Respecto a conectar JS con MySQL..." eso está mal dicho y ni A ni B ni C.

btw tiene pinta de algun problema del encode.. en local que S.O. usas? y en stratos? deduzco que usas entornos distintos, te recomiendo que uses un vagrant con el mismo S.O. que en tu servidor remoto y al menos intenta tener un entorno aislado lo más parecido a producción para evitarte este tipo de problemas.

oFF-sIDE

#19 Probado y funciona perfectamente. Gracias, me he ahorrado poner utf8_encode en todas las consultas ;)

1 1 respuesta
Amazon

#22 es que eso de hacer el encoding en todos lados es:

  • Feo
  • Engorroso
  • Problemático, porque como te olvides una vez, yavestrúz que gracia te va a hacer xD
2 1 respuesta
oFF-sIDE

#23 No puedo estar más de acuerdo :)

RaymaN

Si recoges texto externo en la BD es mejor dejarla en utf8mb4 que acepta emojis.

1 1 respuesta
eXtreM3

#25

Usuarios habituales

  • eXtreM3
  • RaymaN
  • oFF-sIDE
  • Amazon
  • DaRk-eXe
  • NoRelaX