[PHP / Recursie] Waarom werkt deze functie niet?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik heb de volgende array $nodes:
PHP:
1
2
3
4
5
6
7
8
$nodes[1] = array('pid'=>0, 'title'=>'Home'    );
$nodes[2] = array('pid'=>1, 'title'=>'Groenten');
$nodes[3] = array('pid'=>1, 'title'=>'Fruit'   );
$nodes[4] = array('pid'=>1, 'title'=>'Vlees'   );
$nodes[5] = array('pid'=>2, 'title'=>'Zomer'   );
$nodes[6] = array('pid'=>2, 'title'=>'Winter'  );
$nodes[7] = array('pid'=>3, 'title'=>'Rood'    );
$nodes[8] = array('pid'=>3, 'title'=>'Geel'    );

Ik probeer nu een functie (node_list) te schrijven waarmee ik de tree van deze nodes in een tabel weer kan geven. Binnen mijn CMS heb ik een aparte functie om tabellen te maken - de output van node_list moet daarom een array ($rows) zijn. Om eea te vergemakkelijken heb ik een functie nav_child_table, die van elke node de directe kinderen opzoekt:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
function nav_child_table() {
  global $nodes;

  foreach ($nodes as $nid => $node)
  {
    $pid = $node['pid'];
  
    if (isset($children[$pid]))
      $children[$pid][] = $nid;
    else
      $children[$pid] = array($nid);
  }

  return $children;
}

/* output van deze functie:
$children[0] = array(0 => 1);
$children[1] = array(0 => 2, 1 => 3, 2 => 4);
$children[2] = array(0 => 5, 1 => 6);
$children[3] = array(0 => 7, 1 => 8);
*/

function node_list($current_node=1) {
  global $nodes;
  
  $child_table = nav_child_table();

  foreach ($child_table[$current_node] as $child_id)
  {
    $child  = $nodes[$child_id];
    $rows[] = array($child['title'], $child_id); // vereenvoudigd

    if (in_array($child_id, $child_table)
      node_list($child_id);

  }

  return $rows;
}

$rows = node_list();

/* de output die ik wil zou er zo uit moeten zien:
$rows[0] = array('Home', 1);
$rows[1] = array('Groenten', 2);
$rows[2] = array('Zomer', 5);
$rows[3] = array('Winter', 6);
$rows[4] = array('Fruit', 3);
...etc
*/

Ik heb twee problemen:
  • De if (in_array...) conditie (regel 34) is nooit true
  • Als ik de conditie uit regel 34 weglaat, en regel 35 vervang door $rows[] = mode_list($child_id); dan krijg ik een dikke foutmelding, omdat de recursieve output van node_list (zelf al een array) nu aan een andere array wordt toegevoegd!
Wie kan mij vertellen wat ik voud doe en mij in de goede richting duwen om deze functie werkend te krijgen?

P.S - voordat jullie je afvragen waarom ik de output niet in een ordered list stop; de tabel die deze functie genereert wordt gebruikt in het admin deel van de site. Er komen in werkelijkheid nog vele kolommen bij, maar die heb ik hier ter overzichtelijkheid weg gelaten :)

[ Voor 65% gewijzigd door Reveller op 28-02-2005 18:22 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • pjotrk
  • Registratie: Mei 2004
  • Laatst online: 15-07 18:43
Moet de in_array op regel 34 geen array_key_exists() zijn of isset()? want anders doe je in_array( integer, array_van_arrays) wat inderdaad altijd false zal geven :)

dus:
PHP:
1
2
3
isset($child_table[$child_id])
of:
array_key_exists($child_id, $child_table)


het samenvoegen van de arrays op regel 35 kan met array_merge;
PHP:
1
$rows = array_merge($rows, node_list($child_id));

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
pjotrk, je bent een held! Ik zat al uren met dit probleem. Het gebruiken van in_array ipv array_key_exists is gewoon dom. Ik ben de array_merge functie al eens tegen gekomen, maar heb er nog niet eerder zelf mee gewerkt. Daaraan denken is me dan ook ontschoten. Nogmaals bedankt - het scheelt mij ontzettend veel gepruts.

Voor mensen die er nog eens wat aan kunnen hebben, hier compleet:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function node_list($current_node=1) {
  global $nodes;
  
  $child_table = nav_child_table();

  foreach ($child_table[$current_node] as $child_id)
  {
    $child  = $nodes[$child_id];
    $rows[] = array($child['title'], $child_id); // vereenvoudigd

    if (array_key_exists($child_id, $child_table)
      $rows = array_merge($rows, node_list($child_id));

  }

  return $rows;
}

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."