Recientemente estaba trabajando en un proyecto PHP que requerÃa mostrar un árbol de categorÃas de múltiples niveles. He encontrado ciertas soluciones pero no eran lo que yo andaba buscando. No eran totalmente dinámicas, pues contaba con opciones simplemente para unos cuantos niveles. Como no encontré nada para lo que se me solicitaba, es decir, un árbol de categorÃas dinámico y con opción a ser totalmente infinito y cuyos datos se extraigan de una BD MySQL, tuve que implementarlo yo mismo. Asà que, tuve que liarme la manta a la cabeza, y crear este árbol de categorÃas con PHP y MySQL.
El concepto de este script es muy simple y puedes utilizarlo para crear menús, árbol de elementos o cualquier otra cosa que tenga un número desconocido de elementos y de subelementos. He creado una tabla en la base de datos llamada "menus" que contendrá columnas como id, label y parent para crear la estructura de nuestro árbol. Obtendré todos los registros utilizando una consulta SELECT y después, crearé la estructura del árbol. Ojo, lo diseñaré de tal modo que las categorÃas padres se puedan plegar para ocultar a sus hijas.
Habiendo dicho esto, vamos a ver cómo crear un árbol de categorÃas dinámico con PHP.
Crear tabla MySQL
La tabla "menus" contendrá 5 columnas: id (el identificador único), label (será el nombre de la categorÃa), link (enlace de la categorÃa), parent (id de la categorÃa padre) y sort (orden en el que se van a mostrar).
CREATE TABLE IF NOT EXISTS `menus` ( `id` int(11) NOT NULL AUTO_INCREMENT, `label` varchar(50) NOT NULL, `link` varchar(100) NOT NULL, `parent` int(11) NOT NULL DEFAULT '0', `sort` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=17 ;
Inserción de datos
Ahora tenemos que insertar algo de información en nuestra tabla “menus” para crear nuestro árbol de categorÃas. Puedes utilizar estas sentencias de ejemplo:
INSERT INTO `menus` (`id`, `label`, `link`, `parent`, `sort`) VALUES (1, 'PHP', '#', 0, 0), (2, 'Tutorials', '#', 1, NULL), (3, 'Scripts', '#', 1, NULL), (4, 'Arrays', '#', 2, NULL), (5, 'Operators', '#', 2, NULL), (6, 'Arithmetic operators', '#', 5, NULL), (7, 'Assignment operators', '$', 5, NULL), (8, 'Java', '#', 0, NULL), (9, 'Tutorials', '', 8, NULL), (10, 'Programs', '', 8, NULL), (11, 'JavaScript', '#', 0, NULL), (12, 'MySQL', '#', 0, NULL), (13, 'CSS', '', 0, NULL), (14, 'Tutorials', '', 13, NULL), (15, 'Servlet', '', 9, NULL), (16, 'JSP', '', 9, NULL);
Obtener datos de nuestra tabla MySQL
Ahora obtendremos los datos de nuestra tabla “menus” para almacenarlos dentro de un array y pasárselo a la función createTreeView(). Con esta función crearemos nuestro árbol de categorÃas.
<?php $sql = "SELECT id, label, link, parent FROM menus ORDER BY parent, sort, label"; $result = mysqli_query($conn, $sql) or die("database error:". mysqli_error($conn)); // Create an array to conatin a list of items and parents $menus = array( 'items' => array(), 'parents' => array() ); // Builds the array lists with data from the SQL result while ($items = mysqli_fetch_assoc($result)) { // Create current menus item id into array $menus['items'][$items['id']] = $items; // Creates list of all items with children $menus['parents'][$items['parent']][] = $items['id']; } // Print all tree view menus echo createTreeView(0, $menus); ?>
Crear el árbol de categorÃas dinámico
La función createTreeView() funciona de manera recursiva para crear el árbol de categorÃas dinámico.
<?php // function to create dynamic treeview menus function createTreeView($parent, $menu) { $html = ""; if (isset($menu['parents'][$parent])) { $html .= " &lt;ol class='tree'&gt;"; foreach ($menu['parents'][$parent] as $itemId) { if(!isset($menu['parents'][$itemId])) { $html .= "&lt;li&gt;&lt;label for='subfolder2' &gt;&lt;a href='".$menu['items'][$itemId]['link']."'&gt;" .$menu['items'][$itemId]['label']."&lt;/a&gt;&lt;/label&gt; &lt;input type='checkbox' name='subfolder2'/&gt;&lt;/li&gt;"; } if(isset($menu['parents'][$itemId])) { $html .= " &lt;li&gt;&lt;label for='subfolder2'&gt;& lt;a href='".$menu['items'][$itemId]['link']."'&gt;".$menu['items'][$itemId]['label'] ."&lt;/a&gt;&lt;/label&gt; &lt;input type='checkbox' name='subfolder2'/ & gt;"; $html .= createTreeView($itemId, $menu); $html .= "&lt;/li&gt;"; } } $html .= "&lt;/ol&gt;"; } return $html; } ?>
Diseñar el efecto plegable de las categorÃas padre
Ahora, desarrollaremos el efecto plegable de las categorÃas padre de nuestro árbol de categorÃas.
/* CSS to style Treeview menu */ ol.tree { padding: 0 0 0 30px; width: 300px; } li { position: relative; margin-left: -15px; list-style: none; } li input { position: absolute; left: 0; margin-left: 0; opacity: 0; z-index: 2; cursor: pointer; height: 1em; width: 1em; top: 0; } li input + ol { background: url(images/toggle-small-expand.png) 40px 0 no-repeat; margin: -1.600em 0px 8px -44px; height: 1em; } li input + ol > li { display: none; margin-left: -14px !important; padding-left: 1px; } li label { background: url(images/folder.png) 15px 1px no-repeat; cursor: pointer; display: block; padding-left: 37px; } li input:checked + ol { background: url(images/toggle-small.png) 40px 5px no-repeat; margin: -1.96em 0 0 -44px; padding: 1.563em 0 0 80px; height: auto; } li input:checked + ol > li { display: block; margin: 8px 0px 0px 0.125em; } li input:checked + ol > li:last-child { margin: 8px 0 0.063em; }
Fuente: phpzag.com