Cómo mostrar un árbol de categorías dinámico con PHP

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 .= "
      &amp;lt;ol class='tree'&amp;gt;";
       foreach ($menu['parents'][$parent] as $itemId) {
          if(!isset($menu['parents'][$itemId])) {
             $html .= "&amp;lt;li&amp;gt;&amp;lt;label for='subfolder2'
&amp;gt;&amp;lt;a href='".$menu['items'][$itemId]['link']."'&amp;gt;"
.$menu['items'][$itemId]['label']."&amp;lt;/a&amp;gt;&amp;lt;/label&amp;gt;
 &amp;lt;input type='checkbox' name='subfolder2'/&amp;gt;&amp;lt;/li&amp;gt;";
          }
          if(isset($menu['parents'][$itemId])) {
             $html .= "
             &amp;lt;li&amp;gt;&amp;lt;label for='subfolder2'&amp;gt;&amp;
lt;a href='".$menu['items'][$itemId]['link']."'&amp;gt;".$menu['items'][$itemId]['label']
."&amp;lt;/a&amp;gt;&amp;lt;/label&amp;gt; &amp;lt;input type='checkbox' name='subfolder2'/
&amp;
gt;";
             $html .= createTreeView($itemId, $menu);
             $html .= "&amp;lt;/li&amp;gt;";
          }
       }
       $html .= "&amp;lt;/ol&amp;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

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP