Obtenga todos los nodos hijos, nietos, etc. debajo del padre utilizando php con los resultados de la consulta de mysql

He estado tratando de resolver esto, pero no he llegado a ninguna parte. Sinceramente, alguien puede venir a socorrerme.

Mi problema es que estoy usando el modelo de datos de la lista de adyacencia para producir mis datos de jerarquía en mysql. Puedo recuperar la tabla (ver a continuación) en una matriz multidimensional con matriz asociativa para cada elemento. Lo que quiero hacer es que una vez que obtenga esta matriz, quiera obtener otra matriz con todos los nodos (hijo, nieto, etc.) bajo una identificación padre (incluido el elemento principal). No puedo entrenar cómo codificar tihs en php.

En MySQL mi tabla aparece así:

id name parent_id 1 Electronics 0 2 Televisions 1 3 Portable Electronics 1 4 Tube 2 5 LCD 2 6 Plasma 2 7 Mp3 Players 3 8 CD Players 3 9 2 Way Radios 3 10 Flash 7 

Puedo recuperar todas las filas con este código en una matriz asociativa con esto.

 $r = mysql_query("SELECT * FROM test "); $data = array(); while($row = mysql_fetch_assoc($r)) { $data[] = $row; } 

Obtiene resultados:

 Array ( [0] => Array ( [id] => 1 [name] => Electronics [parent_id] => 0 ) [1] => Array ( [id] => 2 [name] => Televisions [parent_id] => 1 ) [2] => Array ( [id] => 3 [name] => Portable Electronics [parent_id] => 1 ) [3] => Array ( [id] => 4 [name] => Tube [parent_id] => 2 ) [4] => Array ( [id] => 5 [name] => LCD [parent_id] => 2 ) [5] => Array ( [id] => 6 [name] => Plasma [parent_id] => 2 ) [6] => Array ( [id] => 7 [name] => Mp3 Players [parent_id] => 3 ) [7] => Array ( [id] => 8 [name] => CD Players [parent_id] => 3 ) [8] => Array ( [id] => 9 [name] => 2 Way Radios [parent_id] => 3 ) [9] => Array ( [id] => 10 [name] => Flash [parent_id] => 7 ) ) 

Con esos resultados quiero filtrarlo con una identificación.

Digamos, por ejemplo, que quería una matriz asociativa de cada nodo en Portable Electronics con el id de 3. (Use id para el código)

Devolvería una matriz con filas con identificadores:

  • 3 Electrónica portátil (se debe incluir el padre seleccionado)
  • 7 reproductores de mp3 (niño)
  • 8 reproductores de CD (niño)
  • 9 radios de 2 vías (niño)
  • 10 Flash (Grand Child)

si Flash tuviera hijos, también los devolvería.

Por lo tanto, el resultado final devolvería una matriz como la de arriba, pero solo con esos elementos.

Tenga en cuenta: no busco una función que cree una matriz multidimensional de la estructura de árbol (Ya obtuve una solución para eso). Deseo crear una función: fetch_recursive ($ id) que reciba una ID y devuelva todos los elementos en ese nivel y en los niveles a continuación, etc. etc.

Espero que esto ayude

Gracias por adelantado

Editar:

Anteriormente había publicado una solución para crear una matriz multidimensional a partir de la salida que daba, así como una manera de obtener todos los elementos secundarios de una id particular fuera de esa matriz en particular. Ahora he descubierto cómo recuperar los elementos secundarios directamente desde su salida (sin tener que pasar primero por una función buildtree() :

 function fetch_recursive($src_arr, $currentid, $parentfound = false, $cats = array()) { foreach($src_arr as $row) { if((!$parentfound && $row['id'] == $currentid) || $row['parent_id'] == $currentid) { $rowdata = array(); foreach($row as $k => $v) $rowdata[$k] = $v; $cats[] = $rowdata; if($row['parent_id'] == $currentid) $cats = array_merge($cats, fetch_recursive($src_arr, $row['id'], true)); } } return $cats; } 

Para usar la función anterior, simplemente pase la matriz de salida $data al primer argumento y la id que desea recuperar los elementos secundarios en el segundo argumento:

ex.:

 $list = fetch_recursive($data, 3); 

Lo cual debería darle la estructura de matriz correcta para id 3 (como se ve en el ejemplo del último cuadro de códigos de esta respuesta).


Respuesta Original:

Nunca había llegado a escribir una función recursiva para construir árboles nesteds a partir de este diseño hasta ahora. Estoy seguro de que hay muchos otros que han escrito funciones similares, pero esta definitivamente debería funcionar para usted:

 function buildtree($src_arr, $parent_id = 0, $tree = array()) { foreach($src_arr as $idx => $row) { if($row['parent_id'] == $parent_id) { foreach($row as $k => $v) $tree[$row['id']][$k] = $v; unset($src_arr[$idx]); $tree[$row['id']]['children'] = buildtree($src_arr, $row['id']); } } ksort($tree); return $tree; } 

Esta función construirá recursivamente un árbol fuera de una lista de adyacencia y mantendrá el ID ordenado en orden ascendente. Esto también hace que las id de cada padre / hijo sean la clave de cada conjunto de información.

Este código:

 $r = mysql_query("SELECT * FROM test "); $data = array(); while($row = mysql_fetch_assoc($r)) { $data[] = $row; } echo '
'; print_r(buildtree($data)); echo '

';

Producirá algo como esto:

 Array ( [1] => Array ( [id] => 1 [name] => Electronics [parent_id] => 0 [children] => Array ( [2] => Array ( [id] => 2 [name] => Televisions [parent_id] => 1 [children] => Array ( [4] => Array ( [id] => 4 [name] => Tube [parent_id] => 2 [children] => Array() ) [5] => Array ( [id] => 5 [name] => LCD [parent_id] => 2 [children] => Array() ) [6] => Array ( [id] => 6 [name] => Plasma [parent_id] => 2 [children] => Array() ) ) ) [3] => Array ( [id] => 3 [name] => Portable Electronics [parent_id] => 1 [children] => Array ( [7] => Array ( [id] => 7 [name] => Mp3 Players [parent_id] => 3 [children] => Array ( [10] => Array ( [id] => 10 [name] => Flash [parent_id] => 7 [children] => Array() ) ) ) [8] => Array ( [id] => 8 [name] => CD Players [parent_id] => 3 [children] => Array() ) [9] => Array ( [id] => 9 [name] => 2 Way Radios [parent_id] => 3 [children] => Array() ) ) ) ) ) ) 

Para obtener todos los nodos secundarios de un id particular en una matriz unidimensional, puede usar esta función:

 function fetch_recursive($tree, $parent_id, $parentfound = false, $list = array()) { foreach($tree as $k => $v) { if($parentfound || $k == $parent_id) { $rowdata = array(); foreach($v as $field => $value) if($field != 'children') $rowdata[$field] = $value; $list[] = $rowdata; if($v['children']) $list = array_merge($list, fetch_recursive($v['children'], $parent_id, true)); } elseif($v['children']) $list = array_merge($list, fetch_recursive($v['children'], $parent_id)); } return $list; } 

Basado en la función buildtree() anterior, digamos que queríamos obtener todos los nodos secundarios de id 3:

 echo '
'; print_r(fetch_recursive(buildtree($a), 3)); echo '

';

Esto dará como resultado:

 Array ( [0] => Array ( [id] => 3 [name] => Portable Electronics [parent_id] => 1 ) [1] => Array ( [id] => 7 [name] => Mp3 Players [parent_id] => 3 ) [2] => Array ( [id] => 10 [name] => Flash [parent_id] => 7 ) [3] => Array ( [id] => 8 [name] => CD Players [parent_id] => 3 ) [4] => Array ( [id] => 9 [name] => 2 Way Radios [parent_id] => 3 ) ) 

Aquí hay una manera de llegar más lejos, y usted puede decidir cómo construye su matriz de resultados y qué campos elige incluir. Esto no está probado, pero deberías ver la lógica.

 // connect to db // set id counter $ids = 0; // declare array $categories = new Array(); // determine max ids $query = mysql_query("SELECT COUNT(1) AS ids FROM test"); $result = mysql_fetch_array(query); // get result $count = $result['ids']; // loop through ids for parents for($ids = 0; $ids <= $count; $ids++) { $query1 = mysql_query("SELECT * FROM test WHERE id = '" . $ids . "'"); $query2 = mysql_query("SELECT id, name, parent_id FROM test WHERE parent_id = '" . $ids . "'"); // check if has children if(mysql_num_rows($query2) > 0) { // iterate through children and add to array while (mysql_fetch_array($query2) as $row) { $categories[$ids]['child'][$row['id']] = $row['name']; } } // check if has siblings if(mysql_num_rows($query1) > 0) { // iterate through children and add to array while (mysql_fetch_array($query2) as $row) { $categories[$ids]['sibling'][$row['id']] = $row['name']; } } }