[PHP/JSON/JS] Hoe een multidimensionaal array uit te lezen?

Pagina: 1
Acties:
  • 750 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Crazybyte
  • Registratie: Juli 2002
  • Laatst online: 15-09 10:07
Situatieschets: Ik heb een dropdown list met daarin een aantal productgroepen en een dropdown list voor producten. De dropdown voor producten wordt gevuld, doormiddel van een AJAX request, op het moment dat iemand een keuze maakt voor een productgroep.

Dit werkte in mijn vorige opzet prima, nu ben ik echter vorige week gebruik gaan maken van het Zend Framework. De implementatie van AJAX vraagt hier om een iets andere aanpak, maar ik heb inmiddels al de nodige tijd besteed om erachter te komen hoe dit werkt, dat is dus ook geen probleem.

Waar ik nu echter niet uit kom is het volgende. In de controller worden met een query de producten opgehaald die behoren bij de gekozen productgroep. Vervolgens worden deze verbouwd naar een array, dat op zijn beurt wordt encoded naar JSON m.b.v. Zend_JSON en tenslotte wordt ge-echo-ed. In JS wordt dit dan weer opgevangen en moet het omgezet worden naar de dropdown.
Bij dat laatste gaat het mis.

Omdat code meer zegt dan een verhaal:

De functie die aangeroepen wordt door de AJAX request:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  function getProductenAction()
  {
    // Model voor producten
    Zend_Loader::loadClass('Products');
    $producten = new Products();
    
    // Het is niet nodig om de view opnieuw te laden
    $this->_helper->viewRenderer->setNoRender();
    
    // ID van de productgroep opvragen en gegevens ophalen
    $id = $this->_request->getParam('groep_id');
    $result = $producten->fetchAll('groep_id = '.$i);
    
    // Resultaat ombouwen zodat we alleen de juiste gegevens hebben
    $tmp = '';
    $i = 0;
    foreach($result as $product)
    {
      $tmp[$i]['product_id'] = $product->product_id;
      $tmp[$i]['omschrijving'] = $product->product_omschrijving;
      $tmp[$i]['artikelnummer'] = $product->artikelnummer;
      $i++;
    }
    
    // Zend_JSON class laden, $tmp encoden naar JSON en terug sturen naar de view
    Zend_Loader::loadClass('Zend_JSON');
    $json = Zend_JSON::encode($tmp);
    echo $json;
  }


De JSON encode string ziet er volgens zo uit:
JSON:
1
2
3
4
5
6
7
8
9
[{"product_id":"229","omschrijving":"deksel jumbo laag","artikelnummer":"090070000"},
{"product_id":"230","omschrijving":"deksel jumbo hoog","artikelnummer":"090070600"},
{"product_id":"279","omschrijving":"deksel B35 compleet","artikelnummer":"090071600"},
{"product_id":"290","omschrijving":"deksel H-200-I compleet","artikelnummer":"090071800"},
{"product_id":"291","omschrijving":"deksel H-200-II compleet","artikelnummer":"090071900"},
{"product_id":"298","omschrijving":"deksel H-200XL-I compleet","artikelnummer":"090072200"},
{"product_id":"299","omschrijving":"deksel H-200XL-II compleet","artikelnummer":"090072400"},
{"product_id":"304","omschrijving":"deksel H200-XL BA","artikelnummer":"062011000"},
{"product_id":"308","omschrijving":"deksel Boxer vertikaal","artikelnummer":"062001300"}]


Het stukje JS dat de JSON string moet uitlezen en omzetten naar de elementen in de dropdown list:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function handleResponse(transport)
{
  // PHP response opslaan in data
  var data = transport.responseText.evalJSON();
  
  // Element dat aangepast moet worden opslaan in dropdownBox
  // en gelijk leeg maken.
  var dropdownBox = document.getElementById('product_id');
  dropdownBox.options.length = 0;
  
  // Een loop om alle gegevens uit data toe te voegen aan de selectbox
  for( ???? )
  {
    var option = document.createElement('option');
    option.value = <<data[i].product_id>>;
    option.appendChild(document.createTextNode(<<data[i].artikelnummer>> + ' - ' + <<data[i].omschrijving>>);
    dropdownBox.appendChild(option);
  }  
}


En bij het stukje "for( ???? )" en op de plekken van <<data[i].waarde>> loop ik dus vast.

Bij de voorbeelden (o.a. deze) die ik gevonden en gebruikt heb is de opbouw van de JSON-string iets anders dan bij die van mij. Daar zitten nog telkens dezelfde identifier voor elke groep van gegevens en nog een algehele identifier. Zie het voorbeeld onder het kopje JSON.

Voor mij zijn er eigenlijk een aantal opties nu:
- Ik codeer in de controller het database resultaat zelf alvast naar het juiste format voor JSON
- Ik maak in de controller van het database resultaat een algemeen object (het resultaat), met daarbinnen allemaal objecten (elke rij uit het resultaat) met hun eigen properties (elke gewenste kolom uit het resultaat). Vervolgens encode ik deze met JSON, in de hoop dat ik nu wel een JSON-string krijg die lijkt op die uit het voorbeeld.
- Er is een mogelijkheid om in JavaScript toch door die JSON-string te wandelen en hem uit te lezen zoals bedoeld. Alleen deze lijk ik maar niet te kunnen achterhalen.

Mijn voorkeur gaat uit naar de laatste optie, bij de 1ste is het gebruik van Zend_JSON overbodig en voor de 2de weet ik niet of Zend_JSON een object wel goed kan omzetten.

Ik hoop dat iemand van jullie mij hieruit kan helpen.

Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Ik zie het probleem eigenlijk niet zo. Het is eigenlijk heel simpel. De variabel data is een simpelweg een Array waarin objecten zitten. Door data heen loopen met een for is dus vrij simpel:
JavaScript:
1
for ( var i = 0; i < data.length; i++ )


Als je dan die << en >> tekens weghaalt, dan ben je er toch al? Of begrijp ik het nu verkeerd?

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Crazybyte
  • Registratie: Juli 2002
  • Laatst online: 15-09 10:07
Michali schreef op maandag 22 oktober 2007 @ 20:12:
Ik zie het probleem eigenlijk niet zo. Het is eigenlijk heel simpel. De variabel data is een simpelweg een Array waarin objecten zitten. Door data heen loopen met een for is dus vrij simpel:
JavaScript:
1
for ( var i = 0; i < data.length; i++ )


Als je dan die << en >> tekens weghaalt, dan ben je er toch al? Of begrijp ik het nu verkeerd?
Ik zal het morgen even proberen, maar als dat het is, dan is het wel heel stom van mij. Dacht alleen dat ik dat al geprobeerd had met data[i] en dat het niet werkte.

Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Het is een kwestie van goed kijken naar hoe je output opgebouwd is qua structuur. In het voorbeeld wat je gaf (op die blog) is het 'root' object een custom object met een property books waarin een Array zit, terwijl het in jouw voorbeeld direct een Array is. In de Array op die blog zitten dan objecten met een enkele property book, die als waarde ook weer een object heeft waarin de werkelijke gegevens zitten. In jou code skip je dat object met die property en heb je direct toegang tot die gegevens.

Ik moet zeggen dat de manier waarop jij je data opbouwt wel wat logischer vind. De output van het voorbeeld in die blog is misschien wat duidelijker als je geen idee hebt wat er uit komt, maar daar is het sowieso niet voor bedoeld, dus eigenlijk is het alleen maar omslachtig. Dus het gewoon houden zoals je het nu hebt, dat is mijns inziens wel een goede manier van werken.

Om het geheel nog wat duidelijker te maken zou ik de variabel data naar books hernoemen. Vervolgens kun je op de eerste regel binnen de for loop dit zetten: var book = books[i];. Dat maakt duidelijk dat je in het geval van books met een collectie boeken te maken hebt, en in met book met een enkel object.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Crazybyte
  • Registratie: Juli 2002
  • Laatst online: 15-09 10:07
Je oplossing werkte, ik snap echt niet dat ik daar zo overheen gekeken heb. Echter staat me ook bij dat ik zoiets al eens geprobeerd had, maar het leek toen niet te werken. In ieder geval bedankt voor je suggesties en hulp.

Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Nog even een suggestie. Je initialiseert de variabel $tmp als een string en gaat hem vervolgens als een array gebruiken. Dat is niet erg netjes, dat zul je zelf ook wel begrijpen. Verander $tmp = ''; daarom even in $tmp = array(); Verder is tmp vrijwel altijd een slechte naam voor een variabel, omdat het helemaal niets zegt. Je geeft hem deze naam waarschijnlijk omdat je er tijdelijk een waarde in opslaat. Echter gebruik je al je variabelen op die manier, dus dan zou je $id, $result, $i etc. ook allemaal dergelijke namen kunnen geven. Dan wordt het er natuurlijk niet duidelijker op. Hernoem hem dus even naar iets dat je meer informatie geeft, zoals $productsInfo oid.

Noushka's Magnificent Dream | Unity

Pagina: 1