Post Top Ad

Your Ad Spot

jueves, 7 de mayo de 2020

MySQL categorías y subcategorías

Trabajar con categorías es una tarea común, también es la necesidad de usar subcategorías, en este tutorial explicaré cómo diseñar un esquema de base de datos para admitir categorías y subcategorías desde una sola tabla. Comencemos con el esquema:
CREATE TABLE `categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL DEFAULT '0',
  `category` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Para almacenar categorías y subcategorías juntas, necesitamos una forma de determinar qué categorías son las subcategorías. Esto se puede lograr mediante la columna parent_id, todas las categorías raíz tendrán un parent_id de 0. Las subcategorías tendrán un parent_id que coincida con el id de la categoría padre.
Agreguemos algunos datos para aclarar esto.
INSERT INTO `categories` (`id`, `parent_id`, `category`) VALUES
(1, 0, 'General'),
(2, 0, 'PHP'),
(3, 0, 'HTML'),
(4, 3, 'Tables'),
(5, 2, 'Functions'),
(6, 2, 'Variables'),
(7, 3, 'Forms');
Aquí tenemos 3 categorías (General, PHP y HTML) y 4 subcategorías.
Una forma más fácil de leer esto:
A partir de esta imagen, podemos ver que Tables es una subcategoría de HTML que podemos ver ya que parent_id es 3 y HTML tiene una identificación de 3.
Ahora podemos ver cómo se almacenan las categorías y subcategorías, pongamos esto en práctica.
Usaré PDO para estos ejemplos:
Conectarse a la base de datos:
$host = "localhost";
$database = "categories";
$username = "root";
$password = "";

$db = new PDO("mysql:host=$host;dbname=$database", $username, $password);

//turn on exceptions
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

//set default fetch mode
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
Ahora seleccione todas las categorías raíz:
$categories = $db->query('SELECT id, parent_id, category FROM categories WHERE parent_id = 0 ORDER BY category');
Ahora recorra las categorías e imprima el título, luego realice otra consulta para llegar a las subcategorías basadas en parent_id y repítalas.
<ul>
<?php
foreach($categories->fetchAll() as $row) {

    echo "<li>$row->category</li>";

    //get child categories
    $children = $db->prepare('SELECT id, parent_id, category FROM categories WHERE parent_id = ? ORDER BY category');
    $children->execute([$row->id]);

    //determine if there are child items
    $hasChildren = $children->rowCount() > 0 ? true : false;

    if ($hasChildren) {
        echo "<ul>";
    }

    foreach($children->fetchAll() as $child) {
        echo "<li>$child->category</li>";
    }

    if ($hasChildren) {
        echo "</ul>";
    }
     
}
?>
</ul>
Un problema de esta configuración es que si hay otro nivel de subcategorías, no se mostrarán a menos que se agregue otro bucle.
Abordemos esto, seleccione todas las categorías independientemente del padre. Agregue todos los resultados como una matriz y páselos a una función llamada generateTree.
$categories = $db->query('SELECT id, parent_id, category FROM categories ORDER BY category');
$rows = $categories->fetchAll(PDO::FETCH_ASSOC);
echo generateTree($rows);
Esta función se repetirá y mostrará el título, y recuperará la función para la profundidad necesaria hasta que todos los bucles hayan terminado.
function generateTree($data, $parent = 0, $depth=0)
{
    $tree = "<ul>\n";
    for ($i=0, $ni=count($data); $i < $ni; $i++) {
        if ($data[$i]['parent_id'] == $parent) {    
            
            $tree .= "<li>\n";
            $tree .= $data[$i]['category'];
            $tree .= generateTree($data, $data[$i]['id'], $depth+1);
            $tree .= "</li>\n";
        }
    }
    $tree .= "</ul>\n";
    return $tree;
}
Lo que genera lo siguiente según estos datos:
INSERT INTO `categories` (`id`, `parent_id`, `category`) VALUES
(1, 0, 'General'),
(2, 0, 'PHP'),
(3, 0, 'HTML'),
(4, 3, 'Tables'),
(5, 2, 'Functions'),
(6, 2, 'Variables'),
(7, 3, 'Forms'),
(8, 5, 'sub 1'),
(9, 8, 'sub 2');
  • General
  • HTML
    • Formas
    • Mesas
  • PHP
    • Las funciones
    • Variables
  • General
    • HTML
      • Formas
        • Mesas
        • PHP
          • Las funciones
            • sub 1
              • sub 2
            • Variables

          No hay comentarios.:

          Publicar un comentario

          Dejanos tu comentario para seguir mejorando!

          outbrain

          Páginas