PHP / MySQL: Multi-nivel del árbol de categorías

  • Impel GD
  • Professor
  • Professor
  • No Avatar
  • Registrado: Oct 26, 2004
  • Mensajes: 834
  • Loc: Cologne, Germany
  • Status: Offline

Nota Noviembre 7th, 2006, 7:49 am

Hola a todos,

Necesito crear un "árbol" de una estructura multi-nivel de la categoría, con una casilla para cada categoría, sobre la base de datos de una tabla MySQL.

Código: [ Select ]
mysql> SELECT ID, ParentID FROM ProductCategories;
+-----+----------+
| ID | ParentID |
+-----+----------+
|  1 |    0 |
|  2 |    0 |
|  3 |    0 |
|  4 |    0 |
|  5 |    0 |
|  6 |    0 |
|  7 |    0 |
|  8 |    0 |
|  9 |    1 |
| 10 |    1 |
| 11 |    1 |
| 12 |    1 |
| 13 |    1 |
| 14 |    1 |
| 15 |    9 |
| 16 |    9 |
| 17 |    9 |
| 18 |    9 |
| 19 |    9 |
| 20 |    9 |
| 21 |    9 |
| 22 |    9 |
| 23 |    9 |
| 24 |    9 |
| 25 |    2 |
| 26 |    2 |
| 27 |    2 |
  1. mysql> SELECT ID, ParentID FROM ProductCategories;
  2. +-----+----------+
  3. | ID | ParentID |
  4. +-----+----------+
  5. |  1 |    0 |
  6. |  2 |    0 |
  7. |  3 |    0 |
  8. |  4 |    0 |
  9. |  5 |    0 |
  10. |  6 |    0 |
  11. |  7 |    0 |
  12. |  8 |    0 |
  13. |  9 |    1 |
  14. | 10 |    1 |
  15. | 11 |    1 |
  16. | 12 |    1 |
  17. | 13 |    1 |
  18. | 14 |    1 |
  19. | 15 |    9 |
  20. | 16 |    9 |
  21. | 17 |    9 |
  22. | 18 |    9 |
  23. | 19 |    9 |
  24. | 20 |    9 |
  25. | 21 |    9 |
  26. | 22 |    9 |
  27. | 23 |    9 |
  28. | 24 |    9 |
  29. | 25 |    2 |
  30. | 26 |    2 |
  31. | 27 |    2 |


Por ejemplo, todas las categorías con un Pare Notid de "1" que aparecen con sangría en la categoría con un ID de "1".

Supongo malos necesidad de crear una matriz multi-dimensional, y luego recorrer para crear la lista, pero soy un poco perdido en cuanto a cómo hacerlo.

Muchas gracias.
Web and print design
  • Anonymous
  • Bot
  • No Avatar
  • Registrado: 25 Feb 2008
  • Mensajes: ?
  • Loc: Ozzuland
  • Status: Online

Nota Noviembre 7th, 2006, 7:49 am

  • Nightslyr
  • Proficient
  • Proficient
  • No Avatar
  • Registrado: Sep 21, 2005
  • Mensajes: 274
  • Status: Offline

Nota Noviembre 7th, 2006, 9:34 am

Im en un poco de una pérdida con lo que usted está tratando de hacer. ¿Son las casillas de algo el usuario tendrá acceso (Im adivinar que es, como su tabla sugiere una tienda)? Cuando la comprobación de las casillas de verificación, desea que los elementos adecuados en esa categoría que se muestra, ¿correcto? Si es así, ¿por qué no utilizar una combinación de PHP y JavaScript?

PHP sería algo así como:
Código: [ Select ]
$query = "SELECT * FROM ProductCategories WHERE ParentID=1";
$result = mysql_query($query);

if(mysql_num_rows($result) > 0){
  echo "<div id="parentCat1">
  while($row = mysql_fetch_assoc($result)){
   //build your items
  }
}

$query = "SELECT * FROM ProductCategories WHERE ParentID=2";
.
.
.
  1. $query = "SELECT * FROM ProductCategories WHERE ParentID=1";
  2. $result = mysql_query($query);
  3. if(mysql_num_rows($result) > 0){
  4.   echo "<div id="parentCat1">
  5.   while($row = mysql_fetch_assoc($result)){
  6.    //build your items
  7.   }
  8. }
  9. $query = "SELECT * FROM ProductCategories WHERE ParentID=2";
  10. .
  11. .
  12. .


Con JavaScript, puede utilizar un controlador de eventos para las cajas de opciones:
Código: [ Select ]
//assuming the checkboxes have a name that follows the ParentID (parent1, parent2, etc)

function init(){

var boxes = new Array();

getBoxes();
attachBoxEvents();
}

function getBoxes(){
  var inputs = document.getElementsByTagName('input');
  for(var i = 0; i < inputs.length; i++){
   if(inputs[i].type == "checkbox" && inputs[i].name.search(/parent/) >= 0){
     boxes[boxes.length] = inputs[i];
   }
  }
}

function attachBoxEvents(){
   for(var i = 0; i < boxes.length; i++){
     boxes[i].onclick = showAndHide();
   }
}

function showAndHide(evt){
  evt = (evt) ? evt : ((event) ? event : NULL);
  if(evt){
   var elem = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : NULL);
   if(elem){
     var index = elem.name.match([0-9]/g);
     var div = document.getElementById('parentCat' + index);
     if(div.style.display == 'block'){
      elem.style.display = '';
     }

     else{
      div.style.display = 'block';
     }
   }
  }
}

window.onload = init;
  1. //assuming the checkboxes have a name that follows the ParentID (parent1, parent2, etc)
  2. function init(){
  3. var boxes = new Array();
  4. getBoxes();
  5. attachBoxEvents();
  6. }
  7. function getBoxes(){
  8.   var inputs = document.getElementsByTagName('input');
  9.   for(var i = 0; i < inputs.length; i++){
  10.    if(inputs[i].type == "checkbox" && inputs[i].name.search(/parent/) >= 0){
  11.      boxes[boxes.length] = inputs[i];
  12.    }
  13.   }
  14. }
  15. function attachBoxEvents(){
  16.    for(var i = 0; i < boxes.length; i++){
  17.      boxes[i].onclick = showAndHide();
  18.    }
  19. }
  20. function showAndHide(evt){
  21.   evt = (evt) ? evt : ((event) ? event : NULL);
  22.   if(evt){
  23.    var elem = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : NULL);
  24.    if(elem){
  25.      var index = elem.name.match([0-9]/g);
  26.      var div = document.getElementById('parentCat' + index);
  27.      if(div.style.display == 'block'){
  28.       elem.style.display = '';
  29.      }
  30.      else{
  31.       div.style.display = 'block';
  32.      }
  33.    }
  34.   }
  35. }
  36. window.onload = init;
  • Impel GD
  • Professor
  • Professor
  • No Avatar
  • Registrado: Oct 26, 2004
  • Mensajes: 834
  • Loc: Cologne, Germany
  • Status: Offline

Nota Noviembre 7th, 2006, 9:58 am

Gracias por la respuesta - lo siento yo no hacer las cosas más claras.

La página en cuestión es parte de un sistema de backend de administración. Las casillas de verificación que he mencionado estará allí para las distintas categorías que se asignará a un producto (más de una categoría se le puede asignar a un solo producto) y cada categoría tendrá lista una casilla de verificación visible permanentemente. Sin embargo, Ill (esperemos) ser capaz de hacer frente a esos yo...

El problema es la salida las distintas categorías en el orden correcto y en la correcta heirachy. Deseo hacer esto de una manera que no se limita a una determinada profundidad, y, naturalmente, acomodar todo lo que se ProductCategories en la tabla. Im esperando para uso ULs anidados.

Edit: He estado buscando a esto tratando de averiguar cómo he podido utilizarlo para hacer el trabajo, pero mi cerebro sufre de sobrecalentamiento. Tengo una comprensión básica de arrays y recordsets, pero estoy atascado en la forma de utilizarlos en este caso.
Web and print design
  • Nightslyr
  • Proficient
  • Proficient
  • No Avatar
  • Registrado: Sep 21, 2005
  • Mensajes: 274
  • Status: Offline

Nota Noviembre 7th, 2006, 10:59 am

Sí, multi-dimensionales puede ser un dolor.

Pregunta: lo que estamos haciendo es dependiente de la jerarquía, correcto? En otras palabras (para usar las cartas como un ejemplo), no se puede tener un gato sin una reina en primer lugar, correcto? Si esa es el caso, a través del bucle array (s) es muy fácil.

El problema es hacer extensible este fin de profundidad no es un problema. Si se trataba de C + +, Id sugiere hacer una serie de listas, con cada elemento en la lista con su propio conjunto con los productos adecuados para ese nivel de la jerarquía, pero Im no está seguro de si PHP tiene la funcionalidad de crear ese tipo de estructura de datos.
  • Impel GD
  • Professor
  • Professor
  • No Avatar
  • Registrado: Oct 26, 2004
  • Mensajes: 834
  • Loc: Cologne, Germany
  • Status: Offline

Nota Noviembre 7th, 2006, 12:02 pm

Sí, el orden de la lista es heirarchy-dependiente en la medida de lo que quiero mostrar de la manera siguiente (basado en el cuadro publicado en el post original):

Código: [ Select ]
Category 1
  Category 9
    Category 15
    Category 16
    Category 17
    Category ...
    Category 24
  Category 10
    etc...
  1. Category 1
  2.   Category 9
  3.     Category 15
  4.     Category 16
  5.     Category 17
  6.     Category ...
  7.     Category 24
  8.   Category 10
  9.     etc...


Cada entrada debe ir acompañada de una casilla de verificación, como se discute.

En realidad he tenido éxito en hacer algo similar con el fin de crear un menú desplegable de dos niveles para el sitio actual, pero, como usted dice, lo hace con independencia del número de niveles en cuestión es más complicada.

PHP puede crear matrices de matrices si eso lo que quieres decir. Así que un elemento dentro de una matriz puede ser una matriz, o no.
Web and print design
  • gisele
  • Expert
  • Expert
  • Avatar de Usuario
  • Registrado: Nov 11, 2004
  • Mensajes: 583
  • Loc: Nimes (France)
  • Status: Offline

Nota Noviembre 8th, 2006, 1:09 am

Hola,

Usted debe mirar en torno a una forma recursiva, su fácil construir un árbol con una opinión de función recursiva.

Sólo tienes que asegurarte de que tu SQL tabla será optimizado con índices de sub cat.

Eche un vistazo a esto:
http://www.ozzu.com/sutra339655.html#339655

particualry perros rabiosos cuando y hablo de una función recursiva y no dude en hacer preguntas si están intersed en este tipo de método.

Podemos ir más allá y yo le puede dar una forma de compensar vista jerárquica (árbol de) refleting las relaciones entre las categorías en su mesa.
____________________
My web site[/url] oh sh..!
  • Impel GD
  • Professor
  • Professor
  • No Avatar
  • Registrado: Oct 26, 2004
  • Mensajes: 834
  • Loc: Cologne, Germany
  • Status: Offline

Nota Noviembre 8th, 2006, 2:19 am

Muchas gracias por el enlace gisele - Im a cabo la mayor parte de hoy Im miedo, sino que leerlo cuando regrese.
Web and print design
  • Impel GD
  • Professor
  • Professor
  • No Avatar
  • Registrado: Oct 26, 2004
  • Mensajes: 834
  • Loc: Cologne, Germany
  • Status: Offline

Nota Noviembre 8th, 2006, 8:41 am

Bien, he leído ahora y ver que la categoría de mesa (s) es / son preguntó por cada lista de categorías. ¿Hay una manera de golpear la base de datos una sola vez, crear un multi-dimensional array de mi mesa y luego recursivamente a través de bucle de la matriz para crear la lista heirarchecal?

Gracias.
Web and print design
  • gisele
  • Expert
  • Expert
  • Avatar de Usuario
  • Registrado: Nov 11, 2004
  • Mensajes: 583
  • Loc: Nimes (France)
  • Status: Offline

Nota Noviembre 8th, 2006, 10:06 am

No es necesario, de hecho, sólo basta para crear una lista en el cuadro principal de productos (números de identificación donde se generan y únicas).

Sommething como:

construido hasta la lista:
[php]
$ q = "SELECT ID, ProductName a partir de productos";
$ r = mysql_query ($ q) or die (mysql_error ()."< br /> <br /> ". $ q);
[/ php]
y para cada elemento que reconstruir la genealogía es llamando a la función recursiva:
[php]
while ($ d = mysql_fetch_array ($ r))
(
echo "<p class=\"node0\">". $ d [1 ]."</ p >";// pantalla nodo 0
single_genealogy ($ d [0], 1); / / obtener y mostrar la filiación con el siguiente nodo 1
)
[/ php]

lo que la función recursiva aspecto tiene?
usted tiene que definir esto, en algún lugar antes de lo anterior:
[php]
función single_genealogy ($ categoría, $ nivel = 0)
(
/ / Los hijos del nodo actual = ID de la que se concilian con esta pare notid
$ q = "SELECT p.ID, producto de los productos unirse ProductCategories USAR (ID) en caso de Pare notID =". $ categoría;
$ r = mysql_query ($ q); / / o morir / mail / echo mysql_error ()
$ nivel + +;
while ($ d = mysql_fetch_row ($ q))
(
echo "<p class=\"node".$level."\">". $ d [1 ]."</ p >";// actual de nodo: $ d [1]
/ / llamada recursiva:
single_genealogy ($ d [0], $ nivel);
)
)
[/ php]

De hecho lo que yo llamo "nodo". $ (node1 node2 node3 etc....) Son las clases CSS para <p> (por ejemplo, con spécifics guión, tamaño)
dependiendo del nivel en el árbol.
Si el odio CSS y sus clases, También puede imaginar un guión simple acumulativo:
con un #definir guión = valor;

y, a continuación,
[php]
echo "<p style=\"text-indent: ".($level * ident)."\">". $ d [1]. "</ p >";// actual de nodo: $ d [1]
[/ php]

Bueno, esa es todo, creo que todos se acaba de ver como esa, ni más, definir la función y, a continuación, aa primera consulta que la lista de productos y sus nombres, y foreach, hemos construido y la pantalla es de filiación.

¿Eso tiene sentido? :-)
____________________
My web site[/url] oh sh..!
  • Impel GD
  • Professor
  • Professor
  • No Avatar
  • Registrado: Oct 26, 2004
  • Mensajes: 834
  • Loc: Cologne, Germany
  • Status: Offline

Nota Noviembre 8th, 2006, 3:15 pm

Muchas gracias gisele - la lista de categorías ya está en marcha!

Obviamente, este método realiza una consulta SELECT cada vez que la función es llamada recursivamente - Me pregunto si hay otra forma. Pero no es realmente una cuestión de todos modos - esto es parte de un sistema de administración y para que no se utilizará todo el tiempo.

Heres el código que he acabado con como por su excelente dirección:

[php] / / Construye lista de categorías
función de las categorías ($ category = 0, $ nivel = 0) (
$ query = "SELECT ID, Pare notID, Nombre ProductCategories DE DONDE Pare notID = $ categoría";
$ result = mysql_query ($ consulta) or die (mysql_error ());
$ nivel + +;
while ($ fila = mysql_fetch_assoc ($ resultado)) (
echo "<p class=\"catnode$level\"> <entrada type = \" checkbox \ "id = \" ; categoría ". $ row [" ID "]." \ "name = \" categoría [ ". $ row [" ID "]."] \ "value = \" 1 \ "> <etiqueta para = \" categoría ". $ Row [" ID "]." \ ">". $ row [ "Nombre"]. "</ etiqueta> </ p> \ n";
categorías ($ row [ "ID"], $ nivel);
)
) [/ php]
Gracias de nuevo. :D
Web and print design
  • gisele
  • Expert
  • Expert
  • Avatar de Usuario
  • Registrado: Nov 11, 2004
  • Mensajes: 583
  • Loc: Nimes (France)
  • Status: Offline

Nota Noviembre 9th, 2006, 1:24 am

Bien,

Su búsqueda es correcto si se quiere:
Todos los niños (ID + Nombre) para un determinado ID y el nombre actual no + id todos los identificadores de los hijos.

Si esto es lo que desea su bien.

Me di cuenta de que usted usa una sola tabla.
¿Quiere decir que cada gato tiene una sola pare no max?
si es así, no hay problema.

O ¿tiene doble a una categoría que tiene más de un pare no (si es posible)?
en ese caso, con algo así como que (n niño <=> n pare desposeídos) que sería mejor dividir a 2 cuadros:
categorías de mesa y las relaciones de mesa, y una consulta como la mía.


Para la ejecución:

de hecho, puede optimizar estas cosas sólo poner un índice en Pare notId, que optimzed donde la cláusula.
Si desea agregar una cláusula ORDER BY, por ejemplo, para ordenar los niños por su nombre, entonces usted tendrá que poner un índice en este campo también.

Para la carga en el servidor MySQL,
Si me dicen que va a tener más de un par de cientos de miles de entradas para un tráfico público que le dirá en serio para comprobar el servidor de recursos a menos que usted haga una mancha de paginación (con un límite en la primera consulta (el que antes de la llamada a las categorías ())

Pero No importa, el uso de esta función recursiva para tareas de administración no hay problema, sólo asegúrate de poner el derecho a fin de que los índices de optimizar la consulta, independientemente del número de categorías están en la tabla.
____________________
My web site[/url] oh sh..!
  • gisele
  • Expert
  • Expert
  • Avatar de Usuario
  • Registrado: Nov 11, 2004
  • Mensajes: 583
  • Loc: Nimes (France)
  • Status: Offline

Nota Noviembre 9th, 2006, 1:36 am

Última cosa muy importante.

Un Id musnt se repetirá en una filiación othewise la función recursiva entrar en bucle para la eternidad.

ejemplo

cat = 1> cat 9 => cat17 => cat9 oups! cat17 => cat9 at17 => cat9 at17 => cat9 at17 => cat9 at17 => cat9 at17 => cat9 at17 => cat9 at17 => cat9..........
____________________
My web site[/url] oh sh..!
  • akazdenko
  • Born
  • Born
  • No Avatar
  • Registrado: Ene 14, 2007
  • Mensajes: 2
  • Loc: Croatia
  • Status: Offline

Nota Enero 14th, 2007, 12:49 pm

Hola a todos...

ive encontrado muy útil este tema y ive tiene una pregunta: Tengo una tabla con id, nombre, y no id_pare i tratado de crear un árbol anidado al igual que ejecución Gd dijo:

Tema 1
--- Tema 2
------ Tema 3
------ Tema 4
--------- Tema 5
Tema 6
Tema 7
--- Tema 8
------ Tema 9
Tema 10 ------
Tema 11 ---------
------------ Tema 12
Tema 13 ---------------
--------------------- Tema 14
------------------- -- Tema 15
Tema 16 ---------
Tema 17

etc...

ive intentado utilizar su código, pero sin éxito :(

cualquier ayuda por favor?

gracias de antemano

Zdenko, Croacia
  • knexor2
  • Proficient
  • Proficient
  • Avatar de Usuario
  • Registrado: May 27, 2006
  • Mensajes: 445
  • Loc: US
  • Status: Offline

Nota Enero 14th, 2007, 11:38 pm

Hice algo parecido a esto una vez. Básicamente, usted tiene una sola tabla con números de identificación automática incrementa, un nombre (por ejemplos bien), y el correspondiente ID no pare, que pare la ID no se refiere a otro tema en la misma mesa, no pare de 0 refiriéndose a una de las máximas a nivel de artículo. En primer lugar, es necesario que la jerarquía resultante estar dentro de una estructura de datos, o puede ser impreso directamente a la página?

De todos modos, la cosa que hice tuvo todos los elementos y pare desposeídos e impresos que la jerarquía de la moda en un <select> (estirada para evitar desplegable acción). Es una solución recursiva, BTW...

El cuadro está formateado como

+-------------------------+
| ID | Nombre | Pare no |

[php]
<? PHP

$ db_host = "localhost";
$ db_un = "username";
$ db_pass = "contraseña";
$ Item_DB = "Base de datos que contiene el tema de mesa";
$ tabla = "tabla que contiene los temas";

$ link = mysql_connect ($ db_host, $ db_un, $ db_pass);

$ tab = ""; / / esto es de 8 espacios, que trabaja como un pseudo-carácter de tabulación dentro de la <option> s
tablvl $ = 1;
función print_kids ($ pos) (/ / $ pos es la posición actual dentro la jerarquía (ID actuales.txt artículos)
global $ enlace;
global $ pestaña;
global $ tablvl;
$ pos = ($ pos? $ pos: null);
$ query = "select * from $ tabla donde no pare". ($ pos == null? "IS NULL": "=".$ pos);
/ / NULL no pare == tema de nivel superior. Para 0-pare desposeídos, en lugar de "es NULL" con "= 0"
$ res = mysql_db_query ($ Item_DB, $ consulta, $ enlace);
if (! $ res) print (mysql_error ());
while ($ fila = mysql_fetch_array ($ res)) (
$ has_kids =
mysql_fetch_array (mysql_db_query ($ Item_DB, "select * from $ tabla donde no pare = $ row [0]", $ link))! = Null;
print ( "<option value=\"$row[0]\">");
for ($ i = 0; $ i <$ tablvl; $ i + +) print ($ tab);
print ( "$ fila [1] </ option> \ n");
if ($ has_kids) (
$ tablvl + +;
print_kids ($ fila [0]); / / llamada recursiva
$ tablvl -;
)
)
)

$ numrows = 1;
$ res = mysql_db_query ($ Item_DB, "SELECT * FROM $ tabla", $ enlace);
while (mysql_fetch_array ($ res)) $ numrows + +;
/ / Sí, Im seguro theres una manera más eficiente manera de hacer esto :P

print ( "<seleccione name=\"hierarchy\" size=\"$numrows\"> \ n");
print ( "<option value=\"null\" selected=\"selected\"> raíz de todos los artículos </ option> \ n");
print_kids ();
print ( "</ select>");

mysql_close ($ enlace);

>
[/ php]

Este es (obviamente? ) Una versión ligeramente modificada de lo que había, sino que debería hacer la misma cosa básica. Espero que ayuda. :D
"People can school you, but you must educate yourself." ~ John Taylor Gatto
Tech Knack Blog
The purpose of these forums is not to get an answer, but to learn an answer.
  • akazdenko
  • Born
  • Born
  • No Avatar
  • Registrado: Ene 14, 2007
  • Mensajes: 2
  • Loc: Croatia
  • Status: Offline

Nota Enero 17th, 2007, 10:21 am

con ligeros cambios ive obtuvo lo que necesito :)

Muchas gracias a personas u foro (especial para thanx knexor2 y gisele)

CYA
  • Anonymous
  • Bot
  • No Avatar
  • Registrado: 25 Feb 2008
  • Mensajes: ?
  • Loc: Ozzuland
  • Status: Online

Nota Enero 17th, 2007, 10:21 am

Publicar Información

  • Total de mensajes en este tema: 18 mensajes
  • Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 234 invitados
  • No puede abrir nuevos temas en este Foro
  • No puede responder a temas en este Foro
  • No puede editar sus mensajes en este Foro
  • No puede borrar sus mensajes en este Foro
  • No puede enviar adjuntos en este Foro
 
 

© 2011 Unmelted, LLC. Ozzu® es una marca registrada de Unmelted, LLC