Créer un JSON dynamique de la foreach

J'utilise les tableaux flottants de jquery pour représenter mes données. Voici l'exemple JSFiddle que j'ai fait qui montre comment les JSONS requis pour le graphique devraient être considérés.

La source de données provient d'une procédure stockée MySql qui possède l'exemple de sortie ci-dessous:

Entrez la description de l'image ici

Je dois représenter dans le graphique, les valeurs de count empilées pour différentes innumber sur l'axe des y, les valeurs de name sur l'axe des abscisses et dans un autre tableau, les valeurs pour l'en- outnumber . (En barres empilées).

-Les séries de données devraient correspondre, de sorte que les étiquettes spécifiques devraient apparaître contre les clients.

Voici le PHP que j'ai jusqu'ici:

 $query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)"); $customers = $query->result_array(); foreach ($customers as $customer) { if($customer['innumber'] != null){ $chartInbound['name'] = $customer['name']; $chartInbound['label'] = $customer['innumber']; $chartInbound['count'] = $customer['count']; $chartInbound['customerid'] = $customer['id']; array_push($out['chartInbound'], $chartInbound); } if($customer['outnumber'] != null){ $chartOutbound['name'] = $customer['name']; $chartOutbound['label'] = $customer['outnumber']; $chartOutbound['count'] = $customer['count']; $chartOutbound['customerid'] = $customer['id']; array_push($out['chartOutbound'], $chartOutbound); } } 

La sortie de print_r($out['chartInbound']); est:

 Array ( [0] => Array ( [name] => 1st Online Solutions [label] => 01-02 [count] => 577 [customerid] => 129 ) [1] => Array ( [name] => Bookngo [label] => 01-02 [count] => 2 [customerid] => 95 ) [2] => Array ( [name] => Boutixury [label] => 07 [count] => 1 [customerid] => 14 ) [3] => Array ( [name] => Cruise Village [label] => 01-02 [count] => 16 [customerid] => 25 ) [4] => Array ( [name] => Cruise Village [label] => 00 [count] => 1 [customerid] => 25 ) [5] => Array ( [customer] => Cruise Village [label] => 07 [countInbound] => 16 [minsInbound] => 125 [customerid] => 25 ) ................... ) 

La sortie de print_r(json_encode($out['chartInbound'])); est:

 [ { "name": "1st Online Soultions" "label": "01-02", "count": "577", "customerid": "129" }, { "name": "Bookngo" "label": "01-020", "count": "2", "customerid": "129" }, { "name": "Boutixury" "label": "07", "count": "1", "customerid": "14" }, { "name": "Cruise Village" "label": "07", "count": "16", "customerid": "25" }, ................. ] 

Mais ce n'est pas très utile.

Q: Comment puis-je créer les JSON dynamiques affichées dans le jsfiddle ci-dessus, à partir des données de la requête?

Passez vos données avec une boucle et newData newTicks tableaux newData et newTicks pour flot à utiliser:

 var newData = []; var newLabels = []; // only used to get index since newData has objects in it var newTicks = []; for (var i = 0; i < dataFromServer.length; i++) { var datapoint = dataFromServer[i]; var tick = newTicks.indexOf(datapoint.name); if (tick == -1) { tick = newTicks.length; newTicks.push(datapoint.name); } var index = newLabels.indexOf(datapoint.label); if (index == -1) { index = newLabels.length; newLabels.push(datapoint.label); newDataPoint = { label: datapoint.label, data: [] }; newDataPoint.data[tick] = [tick, datapoint.count]; newData.push(newDataPoint); } else { newData[index].data[tick] = [tick, datapoint.count]; } } for (var i = 0; i < newTicks.length; i++) { newTicks[i] = [i, newTicks[i]]; } newLabels = null; 

J'ai également dû changer votre génération d'outils puisque votre code n'a fonctionné que lorsque toutes les données étaient terminées et triées. C'est aussi plus simple maintenant.

Violon complet

Juste une idée, je suppose que vous utilisez un groupe dans votre procédure stockée. Si vous pouviez le modifier et ajouter un WITH ROLLUP, la base de données aurait le compte calculé pour vous … Voir https://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html ou recherche SO pour suggestion

Vous pouvez le faire sur le côté client (bien que, idéalement, cela devrait être fait sur le serveur), en utilisant quelque chose comme:

 var table = [ {name: 'a', label: 'l1', count: '15', customerid: '1'}, {name: 'a', label: 'l2', count: '1', customerid: '1'}, {name: 'a', label: 'l3', count: '7', customerid: '1'}, {name: 'b', label: 'l1', count: '3', customerid: '2'}, {name: 'b', label: 'l2', count: '9', customerid: '2'}, {name: 'b', label: 'l3', count: '2', customerid: '2'}, {name: 'c', label: 'l1', count: '1', customerid: '3'}, {name: 'c', label: 'l2', count: '7', customerid: '3'}, {name: 'a', label: 'l3', count: '5', customerid: '4'}, {name: 'a', label: 'l2', count: '6', customerid: '4'} ]; var customers = {}; var labels = {}; var i; for (i = 0; i < table.length; ++i) { customers[table[i].customerid] = table[i].name; labels[table[i].label] = labels[table[i].label] || []; labels[table[i].label].push([+table[i].customerid, +table[i].count]); } var chartData = []; var chartTicks = []; for (customer in customers) { if (customers.hasOwnProperty(customer)) { chartTicks.push([+customer, customers[customer]]); } } for (label in labels) { if (labels.hasOwnProperty(label)) { chartData.push({label: label, data: labels[label]}); } } 

Il compte pour différents clients (clients différents) avec le même nom (bien que Flot ne soit pas vraiment bien lié à cela) et les clients ayant des données manquantes pour certaines étiquettes. Ne devrait pas être trop difficile de déplacer cette logique en PHP, et de le faire sur le serveur.

EDIT: D'accord, je n'avais pas remarqué qu'il agit de façon étrange quand il y a des "lacunes" de l'étiquette. Voici le code révisé:

 var table = [ {name: 'a', label: 'l1', count: '15', customerid: '1'}, {name: 'a', label: 'l2', count: '1', customerid: '1'}, {name: 'a', label: 'l3', count: '7', customerid: '1'}, {name: 'b', label: 'l1', count: '3', customerid: '2'}, {name: 'b', label: 'l2', count: '9', customerid: '2'}, {name: 'b', label: 'l3', count: '2', customerid: '2'}, {name: 'c', label: 'l1', count: '1', customerid: '3'}, {name: 'c', label: 'l2', count: '7', customerid: '3'}, {name: 'a', label: 'l3', count: '5', customerid: '7'}, {name: 'a', label: 'l2', count: '6', customerid: '7'} ]; var customers = {}; var labels = {}; var chartData = []; var chartTicks = []; var i; var customerNo = 0; for (i = 0; i < table.length; ++i) { if(!customers.hasOwnProperty(table[i].customerid)) { customers[table[i].customerid] = table[i].name; chartTicks.push([customerNo, table[i].name]); customerNo++; } labels[table[i].label] = labels[table[i].label] || []; labels[table[i].label].push([customerNo - 1, +table[i].count]); } for (label in labels) { if (labels.hasOwnProperty(label)) { chartData.push({label: label, data: labels[label]}); } } 

Les identifiants d'étiquettes sont donnés dans l'ordre qu'ils apparaissent dans le tableau qui provient du serveur. (Bien qu'il distingue encore deux clients du même nom mais des ID de client différents)

Vous allez devoir transformer les structures vous-même. Vous pouvez soit faire ce côté serveur ou côté client. Dans les deux cas, exécutez les résultats et créez la structure souhaitée. Veillez à essayer d'encoder les tableaux associatifs php chez json et à vous méfier du comportement de NUMERIC_CHECK.

Il semble que vos points de données dans chartTicks[i] doivent correspondre à l'ordre des tiques dans chartData[i].data . Une façon d'assurer une telle concordance est de trier les données par nom dans sql et d'empiler vos résultats par le client d'abord et d'étiqueter le deuxième dans php.

 $query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)"); $customers = $query->result_array(); //should be sorted by name $results = array(); foreach ($customers as $customer) { $i = is_array($results[$customer['name']][$customer['innumber']]) ? count($results[$customer['name']][$customer['innumber']]) : 0; //stack data points by customer name first and label second $results[$customer['name']][$customer['innumber']][] = array($i,$customer['count']); } $chartData = array(); $chartTicks = array(); $i=0; foreach($results as $name => $labels) { $chartTicks[] = array($i++,$name); foreach($labels as $label => $data) { $chartData[] = array( 'label' => $label, 'data' => $data, ); } } print json_encode($chartData); print json_encode($chartTicks); 

Il s'agit d'un moyen concis de transformer votre structure de données JSON actuelle en sortie souhaitée:

 var reduced; var chartData = Object.keys(reduced = data.reduce(function(a, b) { if(a[b.label]) { a[b.label].push([a[b.label].length, parseInt(b.count, 10)]); } else { a[b.label] = [[0, parseInt(b.count, 10)]]; } return a; }, {})).map(function(key) { return { label: key, data: reduced[key] }; }); 

Fiddle: http://jsfiddle.net/rdkgbteq/1/

Voici la même chose en PHP si vous désirez transformer les données sur le serveur:

 $reduced = array_reduce($data, function($result, $current) { if(array_key_exists($current['label'], $result)) { array_push($result, [count($result[$current['label']]), $current['count']]); } else { $result[$current['label']] = [[0, $current['count']]]; } return $result; }, array()); $formatted = array_map(function($key) { return array( 'label' => $key, 'data' => $reduced[$key] ); }, array_keys($reduced)); echo json_encode($formatted); 

Permettez-moi de savoir si vous voulez que je développe ce qui se passe ici.