Artròpodes: AJAX i JSON

De Wikijoan
Revisió de 15:18, 20 set 2018; Joan (Discussió | contribucions)
(dif) ←Versió més antiga | Versió actual (dif) | Versió més nova→ (dif)
Dreceres ràpides: navegació, cerca

Contingut

Introducció

Ja hem vist a classe la sintaxi JSON i per a què ens pot ser útil, concretament en les crides AJAX. En aquesta pràctica generarem un fitxer JSON, insectes.json, amb informació extreta de la base de dades. I després llistarem els insectes de la col.lecció a partir de la informació continguda en el fitxer JSON, i no a partir de la informació de la base de dades.

Referències

Desenvolupament

generar_json_insectes.php

La primera part consisteix en programar un script PHP que ataqui la base de dades i generi el fitxer insectes.json amb la informació i la sintaxi que desitgem.

<?php
/*
Volem escriure un fitxer insectes.json amb la següent sintaxi:
{
"insectes": [
{ "genere":"Acherontia" , "especie":"atropos" },
{ "genere":"Adela" , "especie":"australis" },
{ "genere":"Adelphocoris" , "especie":"vandalicus" },
{ "genere":"Adonia" , "especie":"variegata" },
{ "genere":"Agrypnus" , "especie":"murinus" },
{ "genere":"Akis" , "especie":"tuberculata" }
]
}
és un onbjecte JSON, que conté una matriu de 6 objectes JSON amb dues parelles camp-valor.
*/

include("open_db.php");
$myFile = "insectes.json";
$fh = fopen($myFile, 'w') or die("can't open file");
$sql = "SELECT genere, especie from BUG where genere is not NULL and especie is not NULL";


$result = mysqli_query($conn, $sql);

if (!$result) {
    $message  = 'Invalid query: ' . mysql_error() . "\n";
    die($message);
}
	
fwrite($fh, "{\n");
fwrite($fh, "\"insectes\": [\n");

$i=0;

while ($row = mysqli_fetch_assoc($result)) {
	echo $row['genere']." ".$row['especie']."<br />";
	if ($i > 0) fwrite($fh, ",\n"); //hem d'aconseguir que la última línia no tingui la coma
	$stringInsecte = "{ \"genere\":\"".$row['genere']."\" , \"especie\":\"".$row['especie']."\" }";
	fwrite($fh, $stringInsecte);
	$i++;
}

fwrite($fh, "\n]\n");
fwrite($fh, "}\n");
fclose($fh);
include("close_db.php");

?>

Un cop generat el script has de poder accedir al fitxer JSON des del teu servidor web, per exemple:

llista_insectes_ajax_json.htm

NOTA. En aquest codi d'exemple s'utilitza la funció eval() en comptes de JSON.parse(), que és la que s'ha vist en la teoria. No queda clar si és millor utilitzar una o l'altre, si és que no són equivalents:

En aquest fitxer farem una crida AJAX per recuperar i extreure la informació que hi ha en el fitxe insectes.json. Fixem-nos que no cal que sigui un script PHP, doncs no atacarem a cap base de dades ni farem res de programació en el servidor. Senzillament és una crida AJAX al servidor per recuperar el fitxer insectes.json, i aleshores amb Javascript i la funció eval() processem el text que hem rebut del servidor i el convertim en un objecte Javascript. Aleshores amb tècniques del DOM podem recórrer la llista d'insectes i printar-la per pantalla.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<title>Llista Insectes Col.lecció</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="content-type" content="text/html charset=utf-8" />
<script>
function llistar_insectes()
{
	var xmlhttp;
	var txt;
	if (window.XMLHttpRequest)
	{// code for IE7+, Firefox, Chrome, Opera, Safari
	  xmlhttp=new XMLHttpRequest();
	}
	else
	{// code for IE6, IE5
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}

	xmlhttp.onreadystatechange=function()
	{
		if (xmlhttp.readyState==4 && xmlhttp.status==200)
		{
			txt=xmlhttp.responseText;
			//http://www.javascriptkit.com/dhtmltutors/ajaxgetpost4.shtml
			var jsondata = eval("("+txt+")"); //retrieve result as an JavaScript object
			var rssentries = jsondata.insectes;
			var output = '<ul>';
			for (var i = 0; i < rssentries.length; i++){
			 output += '<li>';
			 output += rssentries[i].genere + ' ' + rssentries[i].especie;
			 output += '</li>';
			}
			output += '</ul>';
			document.getElementById("insectes").innerHTML = output;
		}
	}
	xmlhttp.open("GET","insectes.json",true);
	xmlhttp.send();

}
</script>
</head>
<body onload='llistar_insectes()'>
<h1>Llista dels insectes de la col.lecció</h1>
<div id="insectes">
</div>
</body>
</html>

generar_json_insectes_v2.php

En aquesta segona versió compliquem una mica el fitxer JSON generat. Per cada bitxo, volem mostra la llista (array) de totes les fotos que tenim.

L'estructura del fitxer json que volem obtenir és similar a:

{
"insectes": [

{ "genere":"Acherontia" , "especie":"atropos" , "fotos": ["121018_140043_th.JPG", "121018_140035_th.JPG", "121018_140016_th.JPG"]},

{ "genere":"Adela" , "especie":"australis" , "fotos": ["120501_151328_th.JPG", "120501_151340_th.JPG", "120502_114554_th.JPG", "120502_114604_th.JPG"]},
...
{ "genere":"Zygaena" , "especie":"fausta" , "fotos": ["120909_143404_th.JPG", "120909_143440_th.JPG"]}

]
}

(en realitat, en comptes del nom del fitxer de la foto, obtenim la ruta sencera).

<?php
/*
Volem escriure un fitxer insectes.json amb la següent sintaxi:
{
"insectes": [
{ "genere":"Acherontia" , "especie":"atropos" , "fotos": [ "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG" ]},
{ "genere":"Adela" , "especie":"australis" },
{ "genere":"Adelphocoris" , "especie":"vandalicus" , "fotos": [ "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG" ]},
{ "genere":"Adonia" , "especie":"variegata" , "fotos": [ "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG" ]},
{ "genere":"Agrypnus" , "especie":"murinus" , "fotos": [ "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG" ]},
{ "genere":"Akis" , "especie":"tuberculata" , "fotos": [ "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG", "http://joanqc.no-ip.biz/fotosarthropoda/pics400/12/07/120727_161530_pic.JPG" ]}
]
}

que simlificat seria:

{
"insectes": [
{ "genere":"Acherontia" , "especie":"atropos" , "fotos": [ "120727_161530_pic.JPG", "120727_161530_pic.JPG", "120727_161530_pic.JPG" ]},
{ "genere":"Adela" , "especie":"australis" , "fotos": [ "120727_161530_pic.JPG", "120727_161530_pic.JPG", "120727_161530_pic.JPG" ]},
{ "genere":"Adelphocoris" , "especie":"vandalicus" , "fotos": [ "120727_161530_pic.JPG", "120727_161530_pic.JPG", "120727_161530_pic.JPG" ]},
{ "genere":"Adonia" , "especie":"variegata" , "fotos": [ "120727_161530_pic.JPG", "120727_161530_pic.JPG", "120727_161530_pic.JPG" ]},
{ "genere":"Agrypnus" , "especie":"murinus" , "fotos": [ "120727_161530_pic.JPG", "120727_161530_pic.JPG", "120727_161530_pic.JPG" ]},
{ "genere":"Akis" , "especie":"tuberculata" , "fotos": [ "120727_161530_pic.JPG", "120727_161530_pic.JPG" ]}
]
}
és un onbjecte JSON, que conté una matriu de 6 objectes JSON amb dues parelles camp-valor.
*/

include("open_db.php");
$myFile = "insectes_v2.json";
$fh = fopen($myFile, 'w') or die("can't open file");
$sql = "select B.id_bug, genere, especie, titol, concat('http://joanqc.no-ip.biz/fotosarthropoda/pics400/',substr(nom_fitxer,1,2),'/',substr(nom_fitxer,3,2),'/',replace(nom_fitxer,'.JPG','_pic.JPG')) pic, concat('http://joanqc.no-ip.biz/fotosarthropoda/thumbnails/',substr(nom_fitxer,1,2),'/',substr(nom_fitxer,3,2),'/',replace(nom_fitxer,'.JPG','_th.JPG')) thumb from BUG B, FOTO F where B.id_bug=F.id_bug and genere is not null and especie is not null order by genere, especie, ordre";


$result = mysqli_query($conn, $sql);

if (!$result) {
    $message  = 'Invalid query: ' . mysql_error() . "\n";
    die($message);
}

$i=0;
$mesfotos=0;
$genere="";

fwrite($fh, "{\n");
fwrite($fh, "\"insectes\": [\n");

while ($row = mysqli_fetch_assoc($result)) {
	if ($genere != $row['genere'] || $especie != $row['especie'] ) {
		if ($mesfotos == 1) {
			$stringInsecte = "]}";
			fwrite($fh, $stringInsecte);
			$mesfotos = 0 ;
		}
		echo $row['genere']." ".$row['especie']."<br />";
		if ($i > 0) fwrite($fh, ",\n"); //hem d'aconseguir que la última línia no tingui la coma
		$stringInsecte = "\n";
		$stringInsecte .= "{ \"genere\":\"".$row['genere']."\" , \"especie\":\"".$row['especie']."\" , \"fotos\": [";
		$stringInsecte .= "\"".$row['thumb']."\"";
		fwrite($fh, $stringInsecte);
		$genere = $row['genere'];
		$especie = $row['especie'];
		$mesfotos = 1;

	} else {
		$stringInsecte = ", ";
		$stringInsecte .= "\"".$row['thumb']."\"";
		fwrite($fh, $stringInsecte);
		$mesfotos = 1;
	}
	
	$i++;
}

// sortim del bucle
if ($mesfotos == 1) {
	$stringInsecte = "]}\n";
	fwrite($fh, $stringInsecte);
	$mesfotos = 0 ;
}

fwrite($fh, "\n]\n");
fwrite($fh, "}\n");
fclose($fh);
include("close_db.php");

?>

Un cop generat el script has de poder accedir al fitxer JSON des del teu servidor web, per exemple:

llista_insectes_ajax_json_v2.htm

Llista insectes json.png

Ara ja podem parsejar el fitxer json. Com era d'esperar hi ha dos bucles. El primer bucle recorre tota la llista d'insectes; i per cada insecte, recorrem tota la llista de fotos:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<title>Llista Insectes Col.lecció</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="content-type" content="text/html charset=utf-8" />
<script>
function llistar_insectes()
{
	var xmlhttp;
	var txt;
	if (window.XMLHttpRequest)
	{// code for IE7+, Firefox, Chrome, Opera, Safari
	  xmlhttp=new XMLHttpRequest();
	}
	else
	{// code for IE6, IE5
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}

	xmlhttp.onreadystatechange=function()
	{
		if (xmlhttp.readyState==4 && xmlhttp.status==200)
		{
			txt=xmlhttp.responseText;
			//http://www.javascriptkit.com/dhtmltutors/ajaxgetpost4.shtml
			var jsondata = eval("("+txt+")"); //retrieve result as an JavaScript object
			var rsinsectes = jsondata.insectes;
			var output = '<ul>';
			for (var i = 0; i < rsinsectes.length; i++){
				 output += '<li>';
			 	output += rsinsectes[i].genere + ' ' + rsinsectes[i].especie;
				var rsfotos = rsinsectes[i].fotos;
				outputfotos = '<br />';	
				for (var j = 0; j < rsfotos.length; j++){
					outputfotos += '<img src="' + rsfotos[j] + '" /> ';
				}
				//outputfotos += '</ul>';
			 	output += outputfotos;
			 	output += '</li>';
			}
			output += '</ul>';
			document.getElementById("insectes").innerHTML = output;
		}
	}
	xmlhttp.open("GET","insectes_v2.json",true);
	xmlhttp.send();

}
</script>
</head>
<body onload='llistar_insectes()'>
<h1>Llista dels insectes de la col.lecció</h1>
<div id="insectes">
</div>
</body>
</html>

Millora: generar_json_insectes_v3.php

Anem a simplificar el procés. A partir de les dades que vénen de la consulta SQL, anem a omplir una matriu, i aquesta matriu la convertirem directament a una matriu JSON gràcies a la funció json_encode. D'aquesta manera simplifiquem bastant, sobretot la sintaxi, i així ens evitem cometre errors comuns de sintaxi amb les comes, claus, dobles comes, etc.

generar_json_insectes_v3.php:

<?php
/*
Volem escriure un fitxer insectes.json amb la següent sintaxi:
{
"insectes": [
{ "genere":"Acherontia" , "especie":"atropos" },
{ "genere":"Adela" , "especie":"australis" },
{ "genere":"Adelphocoris" , "especie":"vandalicus" },
{ "genere":"Adonia" , "especie":"variegata" },
{ "genere":"Agrypnus" , "especie":"murinus" },
{ "genere":"Akis" , "especie":"tuberculata" }
]
}
és un onbjecte JSON, que conté una matriu de 6 objectes JSON amb dues parelles camp-valor.
*/

include("open_db.php");
$myFile = "insectes_v3.json";
$fh = fopen($myFile, 'w') or die("can't open file");
$sql = "SELECT genere, especie from BUG where genere is not NULL and especie is not NULL";


	

$jsonArray = array();
$result = mysqli_query($conn, $sql);

if (!$result) {
    $message  = 'Invalid query: ' . mysql_error() . "\n";
    die($message);
}
	
fwrite($fh, "{\n");
fwrite($fh, "\"insectes\":");

while ($row = mysqli_fetch_assoc($result)) {

	$jsonArrayItem = array();
	$jsonArrayItem['genere'] = $row['genere'];
	$jsonArrayItem['especie'] = $row['especie'];
	array_push($jsonArray, $jsonArrayItem);

}

include("close_db.php");
//header('Content-type: application/json');
fwrite($fh, json_encode($jsonArray));
fwrite($fh, "\n}\n");
fclose($fh);
echo "S'ha generat el fitxer insectes_v3.json"
?>

Més informació:

Per provar aquest exemple pots modificar el primer exemple llista_insectes_ajax_json.htm, i ficar la nova versió insectes_v3.json.

Un altre mètode: no cal generar els fitxer json

En els anteriors exemples hem generat els fitxers .json com a pas previ, però de fet no cal. Fem-ho amb el primer exemple:

fitxer llista_insectes_ajax_json_directe.htm:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<title>Llista Insectes Col.lecció</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="content-type" content="text/html charset=utf-8" />
<script>
function llistar_insectes()
{
	var xmlhttp;
	var txt;
	xmlhttp=new XMLHttpRequest();


	xmlhttp.onreadystatechange=function()
	{
		if (xmlhttp.readyState==4 && xmlhttp.status==200)
		{
			txt=xmlhttp.responseText;
			//http://www.javascriptkit.com/dhtmltutors/ajaxgetpost4.shtml
			var jsondata = eval("("+txt+")"); //retrieve result as an JavaScript object
			var rssentries = jsondata.insectes;
			var output = '<ul>';
			for (var i = 0; i < rssentries.length; i++){
			 output += '<li>';
			 output += rssentries[i].genere + ' ' + rssentries[i].especie;
			 output += '</li>';
			}
			output += '</ul>';
			document.getElementById("insectes").innerHTML = output;
		}
	}
	xmlhttp.open("GET","generar_json_insectes_directe.php",true);
	xmlhttp.send();

}
</script>
</head>
<body onload='llistar_insectes()'>
<h1>Llista dels insectes de la col.lecció</h1>
<div id="insectes">
</div>
</body>
</html>

Fitxer generar_json_insectes_directe.php:

<?php
/*
Volem formatar una cadena amb la següent sintaxi:
{
"insectes": [
{ "genere":"Acherontia" , "especie":"atropos" },
{ "genere":"Adela" , "especie":"australis" },
{ "genere":"Adelphocoris" , "especie":"vandalicus" },
{ "genere":"Adonia" , "especie":"variegata" },
{ "genere":"Agrypnus" , "especie":"murinus" },
{ "genere":"Akis" , "especie":"tuberculata" }
]
}
és un onbjecte JSON, que conté una matriu de 6 objectes JSON amb dues parelles camp-valor.
*/

include("open_db.php");

$sql = "SELECT genere, especie from BUG where genere is not NULL and especie is not NULL";


$result = mysqli_query($conn, $sql);

if (!$result) {
    $message  = 'Invalid query: ' . mysql_error() . "\n";
    die($message);
}
	
$cad = "";

$cad .= "{\n";
$cad .= "\"insectes\": [\n";

while ($row = mysqli_fetch_assoc($result)) {
	//echo $row['genere']." ".$row['especie']."<br />";
	if ($i > 0) $cad .= ",\n"; //hem d'aconseguir que la última línia no tingui la coma
	$stringInsecte = "{ \"genere\":\"".$row['genere']."\" , \"especie\":\"".$row['especie']."\" }";
	$cad .= $stringInsecte;
	$i++;
}

$cad .= "\n]\n";
$cad .= "}\n";
include("close_db.php");

echo $cad;
?>

Objecte PHP -> JSON -> Objecte javascript

Diferència entre JSON.parse() i eval:

objecte_insectes.php:

<?php
/*
{
"insectes": [
{ "genere":"Acherontia" , "especie":"atropos" },
{ "genere":"Adela" , "especie":"australis" },
{ "genere":"Adelphocoris" , "especie":"vandalicus" },
{ "genere":"Adonia" , "especie":"variegata" }
]
}
*/

$array[] = new stdClass;
$array[0]->genere = "Acherontia";
$array[0]->especie = "atropos";
$array[] = new stdClass;
$array[1]->genere = "Adela";
$array[1]->especie = "australis";
$array[] = new stdClass;
$array[2]->genere = "Adelphocoris";
$array[2]->especie = "vandalicus";
$array[] = new stdClass;
$array[3]->genere = "Adonia";
$array[3]->especie = "variegata";

$myObj = new \stdClass();
$myObj->insectes = $array;
$myJSON = json_encode($myObj);
echo $myJSON;

?>

llista_insectes_from_php_object.htm:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<title>Llista Insectes Col.lecció</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="content-type" content="text/html charset=utf-8" />
<script>
function llistar_insectes()
{
	var xmlhttp;
	var txt;
	xmlhttp=new XMLHttpRequest();


	xmlhttp.onreadystatechange=function()
	{
		if (xmlhttp.readyState==4 && xmlhttp.status==200)
		{
			txt=xmlhttp.responseText;
			//https://stackoverflow.com/questions/1843343/json-parse-vs-eval
			//var jsondata = eval("("+txt+")"); //retrieve result as an JavaScript object
			var jsondata = JSON.parse(txt);
			var rssentries = jsondata.insectes;
			var output = '<ul>';
			for (var i = 0; i < rssentries.length; i++){
			 output += '<li>';
			 output += rssentries[i].genere + ' ' + rssentries[i].especie;
			 output += '</li>';
			}
			output += '</ul>';
			document.getElementById("insectes").innerHTML = output;
		}
	}
	xmlhttp.open("GET","objecte_insectes.php",true);
	xmlhttp.send();

}
</script>
</head>
<body onload='llistar_insectes()'>
<h1>Llista dels insectes de la col.lecció</h1>
<div id="insectes">
</div>
</body>
</html>

Conclusió

Veiem doncs que hi ha moltes maneres d'intercanviar la informació entre el client i el servidor. La comunicació del protocol TCP sempre són bytes que representem com a cadenes de text. Però aquestes de text tenen molts avantatges si el seu format és JSON, doncs tan en el cantó del client com en el cantó del servidor podem convertir el format JSON a objectes; o d'objectes al format JSON.

Feina per l'alumne

Els exemples vistos anteriorment creen amb PHP els fitxers JSON, i des del fitxer del front-end (htm) cridem directament al fitxer JSON. Pots entendre que aquest procés es pot simplificar: el fitxer html que fa la crida AJAX crida al fitxer PHP que construeix una cadena JSON que la retornem al front-end. És a dir, no cal crear els fitxers .json. Repeteix els exercicis anteriors sense crear els fitxers .json.

L'exemple vist és un exemple mínim en què mostrem el genere i espècie continguts en la taula BUG. Se't demana que combinis la taula BUG amb la taula FOTO per extreure el titol, nom_cat, genere, especie, BUG.notes, nom_fitxer. Has d'utilitzar només la primera FOTO per cada BUG, ordre=1, igual que en l'anterior pràctica. Fiques tota la informació en el fitxer insectes_extens.json.

Mostra tota aquesta informació de forma adequada en la pàgina. Mostra també la miniatura de la foto. Utilitza un full d'estils adequat.

Entrega

Els alumnes entregaran al Schoology tots els fitxers generats (fitxers html). S'empaquetaran tots aquests fitxers i es pujaran al Schoology dins del termini d'entrega de la pràctica.

Recorda la normativa per entregar les pràctiques al Google Classroom: ASIX-M10-UF2#Normativa_d.27entrega_de_les_pr.C3.A0ctiques_al_Schoology


creat per Joan Quintana Compte, febrer 2019

Eines de l'usuari
Espais de noms
Variants
Accions
Navegació
Institut Jaume Balmes
Màquines recreatives
CNC
Informàtica musical
joanillo.org Planet
Eines