listado de temas

Menues anidados: ¿Cuál es la mejor forma de programar un menu con varios niveles de categorias y subcategorias?


Leido: 1034 veces

Este pregunta siempre me la hacia.

Hace poco me tocó hacer un trabajo para España, donde me pasaron una base de datos sql server 2005 y despues de mucho lugar logré restaurarla en mi equipo local.

Bueno, viendo las estructuras de las tablas encontré un diseño de menú con categorias padre, hijas, nietas muy interesante que voy a comentar a continuación dado que entiendo que puede salvarle las papas a mas de 1 (me incluyo!)

Cuando tengas que programar una estructura de menu con varios niveles de anidamiento (padre, hijos, nietos, etc) usá la siguiente estructura de tablas:

categorias=(@id,nombre,niveles,nivel_padre)

donde:
  • id: es la clave de la categoria
  • nombre: es el nombre de la categoria
  • niveles: string de ids de categorias separados por algun caracter especial, como ser: .
  • nivel_padre: id de la categoria padre (o NULL)


Ejemplo: entonces tendríamos lo siguiente en categorias:
  • 1,congelados,null,null
  • 12,productos lacteos,1.12,1
  • 43,leche,1.12.43,12
  • 45,queso,1.12.45,12


para formar la siguiente estructura:
  • congelados
  • -productos lacteos
  • --leche
  • --queso


y lo mejor es que para totalizar es super facil, haciendo: select count(*) as total from categorias where nivel_padre=un_id esto nos da el total de niveles de una categoria.

saludos!

Walter
Publicado por: wm mk | 24/09/2009 10:23:09 | IP: 200.55.10.227

listado de temas


Comentarios sobre esta entrada (5)

Hola Diego.

Lo anteriormente expuesto es la estructura de base de datos necesaria para almacenar el menú. Para imprimirlo necesitás un algorítmo recursivo de árboles n-arios (múltiples ramas). No te asustes, es bastante simple.

No estoy de acuerdo con lo de que hay que actualizar toda la estructura. No hay que actualizar nada. Y lo explico a continuación.

Todo árbol tiene 1 y sólo 1 raíz. La raíz, tiene id_menu=0, NO SE IMPRIME. Y el campo niveles de la raiz contiene el orden de impresión de las ramas superiores del árbol que forma el menú. Notar que en el caso de la raíz, el campo niveles te indica el orden de impresión de las ramas EN EL SENTIDO DESDE LA RAIZ HACIA ABAJO (en el resto de la estructura en al reves).

Si vos partis del siguiente menu:
0
  1 autos
    2 ford
    3 chevrolet
  4 bicicletas
    5 giant
    6 trek
y te piden que entre los autos y las bicicletas metas las motos, en lugar de mover las bicicletas, lo que haces es insertarlo a continuacion (con el siguiente numero en la secuencia incremental o sea el 7)
0
  1 autos
    2 ford
    3 chevrolet
  4 bicicletas
    5 giant
    6 trek
  7 motos
    8 vmw
esto es a nivel de base de datos. A nivel visual si vos quisieras imprimir en el siguiente orden: autos, motos, bicicletas (o sea, intercalando el menu motos entre autos y bicicletas) lo que tenes que hacer es armar un arbol n-ario con esta estructura. La raiz del arbol tendrá código 0 y padre NULL (sin padre) y el campo "niveles" de la raíz te indicará el orden en el que se deben imprimir. Esto se hace así por 3 cosas: 1) los árboles deben tener una raíz, por mas que tengan n-ramas, deben partir de 1 raíz (que no se muestra) 2) te permite cambiar EN EL ACTO Y SIN RE-ASIGNAR NADA DE NADA, el orden de las ramas. Es decir, en la raíz vos tenés en el campo niveles lo siguiente: 1|7|4 lo que te indica que querés imprimir: autos seguido de motos seguido de bicicletas. Si el día de mañana te cambian el orden a autos seguido de bicicletas seguido de motos, vos haces: 1|4|7 y listo! el algortítmo de impresión del menú es recursivo. Y lo encontrarás en cualquier sitio de programación. Es bastante básico. En cuanto tenga 5 minutos disponibles lo subo yo 3) este menu es totalmente escalable, en el sentido que puede crecer indefinidamente con n-niveles de anidamineto.

otro ejemplo: ahora supongamos que te piden agregar las categorias rutera y MT B (Mountain Bike) en Giant, nos queda así:
0
  1 Autos
    2 Ford
    3 VW
  4 Bicicletas
    5 Giant
      9 Giant rutera
      10 Giant MTB
    6 Trek
  7 Motos
    8 BMW


a nivel base de datos tendías:
id_menunombreid_menu_padreniveles
0NULL1|7|4 (indica el orden de impresión de los menues superiores)
1Autos00|1
2Ford10|1|2
3VW10|1|3
4Bicicletas00|4
5Giant40|4|5
6Trek40|4|6
7Motos00|7
...(sigue)...


Acabamos de intercalar 2 categorías en Giant y realizamos cero movimientos en la base de datos. No re-asignamos nada como verás. Simplemente seguimos usando el siguiente dígito en la secuencia.



Sí o sí necesitas enteder como funciona 1 algorítmo recursivo para poder manejar esto. Es la forma mas eficiente de imprimir una estructura de estas características.

Cualqueir duda consultame, si estoy libre de tiempo te respondo mejor.



saludos,

Walter
Publicado por: wm mk | 28/09/2009 20:49:51 | IP: 190.18.66.115
Esta bueno, pero aca me dijeron que no lo haga asi.

Lo que me cuestionan es que si despues que pusiste toda la estructura de niveles en todos los registros, si despues llegas a tener que cambiar algun nivel deberias actualizar el cambio en todos los registros uno por uno.

Dicen que no es practico. A mi no me parece mucho lio, pero me dicen que lo haga "como corresponde". Son unos giles.

Cual seria el problema de actualizar todo cada vez que modificas algo walter?

Te mando un saludo!
Publicado por: Diego Arregui | 28/09/2009 16:56:48 | IP: 190.179.27.110
Hola Diego Arregui,

Gracias por participar.

No lo copie, lo trascribí. El campo niveles se usa para tener en 1 solo campo toda la estructura de niveles desde el primer padre hasta el último de los hijos.

Por ejemplo, cuando pongo: (13234,leche en polvo,1.12.43.13234,43) el 1.12.42.12324 es la estructura jerárquica de niveles.

Si usas PHP podes rápidamente obtener todos los niveles haciendo: $arr_niveles=explode(".",niveles); de esta forma en la variable-arreglo $arr_niveles tendras todos los niveles de la estructura. De esta forma no tenes que hacer otra consulta SQL para obtener la estructura de niveles.

Que bueno que te sirva.

Cualquier cosa escribí aca de nuevo.

saludos,



Walter
Publicado por: wm mk | 25/09/2009 16:05:57 | IP: 200.55.10.227
Grande flaco!! me viene barbaro esto. Necesito hacer algo parecido pero con mysql, supongo que es lo mismo no?

Recien entro en el laburo y me encargaron hacer algo parecido a esto y no caso una!!! :)

Recien empiezo sabés? hice el curso de php y vi algo de mysql, pero me las rebusco.

Mató tu explicacion, es muy clara, pero sabes lo que no entiendo? para que es el campo niveles. Para que lo usas? me da la sensacion que lo copiaste y lo pegaste nomas, pero no se usa.

Bueno, te dejo un saludo y gracias por el aporte!! 10 puntos todo!!

Diego Arregui



Publicado por: Diego Regui | 25/09/2009 15:40:43 | IP: 190.179.4.222
Olvidé decir que esta estructura de tablas es totalmente escalable.

Para agregar un cuarto nivel de anidamiento simplemente debemos agregar un registro de la forma: (13234,leche en polvo,1.12.43.13234,43)

de esta forma tendríamos:
  • congelados
  • -productos lacteos
  • --leche
  • ---leche en polvo


saludos,



Walter
Publicado por: wm mk | 24/09/2009 10:27:49 | IP: 200.55.10.227


Agregar comentario

título *
mensaje *
imagen
nombre *
apellido *
email * (se te enviará un email con un enlace de validación)
web
teléfono mobil (no será publicado)
*=obligatorio
captcha : ingrese el codigo que aparece en la imagen

[ si no logra ver la imagen haga clic aquí ]

listado de temas
RSS libroutil.com megabuscador de libros ofertas de trabajo IT quejas y reclamos
red social
SAP BI/BW
blog desarrollado por: wmmk.com.ar