Ene
16.
En un proyecto que realicé hace poco tuve que implementar un menú en forma de arbol de categorías, con distintos niveles de subcategorías y, como no, que fuera accesible.
La tabla donde se almacena los datos de cada familia tiene los siguientes campos:
- id_familia: INT primary key
- padre: INT indica el id de la familia padre. Será 0 cuando no tenga padre
- nivel: INT indica el nivel de profundidad en el arbol de categorías. Las familas con padre 0 tienen nivel 0.
- nombre_es: VARCHAR nombre de la familia
El código del ejemplo es el siguiente:
<?php
//se declara la variable global $nivel para tener una referencia fuera de la función recursiva que indique el nivel de profundidad de subfamilia actual
$nivel = "";
global $nivel;
///funcion recursiva que recorre el menu
function recorrer_menu_familias($padre, $nivel_anterior){
//la consulta a la tabla familias busca los hijos del padre que entró como parametro a esta función
$sql="SELECT id_familia, padre, nivel, nombre_es FROM familias WHERE padre = $padre";
$result=mysql_query($sql);
while($row = mysql_fetch_array($result)){
if($GLOBALS['nivel']=="")
//si la goblal nivel está vacia es que acaba de empecar el ciclo recursivo
echo "<li>\n";
else{
//según la diferencia de nivel actual con el anterior guardada en $GLOBALS['nivel'] se cierran o abren etiquetas <Li>
$diferencia = $row['nivel'] - $GLOBALS['nivel'];
if($diferencia==0) echo "</li>\n<li>\n"; //no ha cambiado de nivel de subfamilia respecto al anterior
if($diferencia==1) echo "<ul>\n<li>\n"; //ha subido un nivel de subfamilia respecto al anterior
if($diferencia==-1) echo "</li>\n</ul>\n<li>\n"; //ha bajado un nivel de subfamilia respecto al anterior
if($diferencia < (-1)){
//baja varios niveles de subfamilia respecto al anterior
echo "</li>";
for($i=$diferencia;$i<0;$i++)
echo "</ul>\n</li>\n";
echo "<li>\n";
}
}
//crea el enlace
echo "<a href='?fam=".$row['id_familia']."'>".$row['nombre_es']."</a>";
//actualiza $GLOBALS['nivel'] al nivel actual
$GLOBALS['nivel'] = $row['nivel'];
//se llama a si mismo para comprovar quienes son los hijos de la familia actual
recorrer_menu_familias($row['id_familia'],$row['nivel']);
}
}
//muestra menu
function muestra_menu_familias(){
recorrer_menu_familias(0, "");
echo "</li>\n";
for($i=0;$i==$GLOBALS['nivel'];$i++)
echo "</ul>\n</li>\n";
}
?>
<ul>
<?php muestra_menu_familias(); ?></ul>
//se declara la variable global $nivel para tener una referencia fuera de la función recursiva que indique el nivel de profundidad de subfamilia actual
$nivel = "";
global $nivel;
///funcion recursiva que recorre el menu
function recorrer_menu_familias($padre, $nivel_anterior){
//la consulta a la tabla familias busca los hijos del padre que entró como parametro a esta función
$sql="SELECT id_familia, padre, nivel, nombre_es FROM familias WHERE padre = $padre";
$result=mysql_query($sql);
while($row = mysql_fetch_array($result)){
if($GLOBALS['nivel']=="")
//si la goblal nivel está vacia es que acaba de empecar el ciclo recursivo
echo "<li>\n";
else{
//según la diferencia de nivel actual con el anterior guardada en $GLOBALS['nivel'] se cierran o abren etiquetas <Li>
$diferencia = $row['nivel'] - $GLOBALS['nivel'];
if($diferencia==0) echo "</li>\n<li>\n"; //no ha cambiado de nivel de subfamilia respecto al anterior
if($diferencia==1) echo "<ul>\n<li>\n"; //ha subido un nivel de subfamilia respecto al anterior
if($diferencia==-1) echo "</li>\n</ul>\n<li>\n"; //ha bajado un nivel de subfamilia respecto al anterior
if($diferencia < (-1)){
//baja varios niveles de subfamilia respecto al anterior
echo "</li>";
for($i=$diferencia;$i<0;$i++)
echo "</ul>\n</li>\n";
echo "<li>\n";
}
}
//crea el enlace
echo "<a href='?fam=".$row['id_familia']."'>".$row['nombre_es']."</a>";
//actualiza $GLOBALS['nivel'] al nivel actual
$GLOBALS['nivel'] = $row['nivel'];
//se llama a si mismo para comprovar quienes son los hijos de la familia actual
recorrer_menu_familias($row['id_familia'],$row['nivel']);
}
}
//muestra menu
function muestra_menu_familias(){
recorrer_menu_familias(0, "");
echo "</li>\n";
for($i=0;$i==$GLOBALS['nivel'];$i++)
echo "</ul>\n</li>\n";
}
?>
<ul>
<?php muestra_menu_familias(); ?></ul>
Y aplicando al resultado obtenido un buen aspecto con Treeview de jQuery http://docs.jquery.com/Plugins/Treeview da como resultado un arbol de categorías bastante elegante.

