New question

Question:

Date: 20-05-2019 10:23:42 (In Spanish)

Listar dinámicamente categorías y sub categorías de una sola tabla con PHP y MySQL[Resolved]

Saludos a todos, estoy intentando seleccionar un listado de categorías que tienen sub categorías, éstos además otras sub sub categorías y así sucesivamente.

El esquema sería mas o menos así:
_Categoría 01
___ Sub categoría 01
___ Sub categoría 02
_____ Sub sub categoría 01
_______ Sub sub sub categoría 01
_______ Sub sub sub categoría 02
_______ .
_______ .
_______ Sub sub sub categoría nn
_____ .
_____ .
_____ Sub sub categoría nn
___ .
___ .
___ Sub categoría nn
_Categoría 02
___ Sub categoría 01
___ Sub categoría 02
_ .
_ .
_Categoría nn
___ Sub categoría nn

Los guión bajo + punto (_ .) indica que habrá muchos más items

/* ------------------------------------------------------------- */
Aquí va el código

Base de DATOS

CREATE TABLE `categorias` (
  `id_cat` int(11) NOT NULL,
  `cat_title` varchar(250) NOT NULL,
  `cat_parent` int(11) NOT NULL,
  `cat_order` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `categorias` (`id_cat`, `cat_title`, `cat_parent`, `cat_order`) VALUES
(1, 'Categoría 01', 0, 1),
(2, 'Categoría 02', 0, 2),
(3, 'Sub Categoría 01', 1, 1),
(4, 'Sub sub Categoría 01', 3, 1),
(5, 'Categoría 03', 0, 3),
(6, 'Sub Categoría 02', 1, 2),
(7, 'Sub Categoría 01', 5, 2),
(8, 'Categoría 04', 0, 4),
(9, 'Sub sub Categoría 02', 3, 2),
(10, 'Sub sub Categoría 03', 3, 3);


/*-----------------------------------------------*/
CONSULTA PHP + ESTRUCTURA HTML
<?php
function consulta($id){
	$cn = mysqli_connect("localhost", "root", "", "prueba_db");
	$sql = "SELECT * FROM categorias WHERE cat_parent = '$id' ORDER BY cat_order asc";
	return mysqli_query($cn, $sql);
}
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>PRUEBA CONSULTA</title>
	<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" title="all" />
</head>
<body>
	<table class="table table-bordered" style="max-width: 600px; margin: 20px auto">
		<thead>
			<tr>
				<th>ID</th>
				<th>Title</th>
				<th>Parent</th>
				<th>Order</th>
			</tr>
		</thead>
		<tbody>
			<?php foreach(consulta(0) as $row) : ?>
				<tr>
					<td><?php echo $row['id_cat'] ?></td>
					<td><?php echo utf8_encode($row['cat_title']) ?></td>
					<td><?php echo $row['cat_parent'] ?></td>
					<td><?php echo $row['cat_order'] ?></td>
				</tr>
				<?php
					foreach (consulta($row['id_cat']) as $row2) {?>
					<tr>
						<td><?php echo $row2['id_cat'] ?></td>
						<td>_ <?php echo utf8_encode($row2['cat_title']) ?></td>
						<td><?php echo $row2['cat_parent'] ?></td>
						<td>_ <?php echo $row2['cat_order'] ?></td>
					</tr>
				<?php
						foreach (consulta($row2['id_cat']) as $row3) {?>
						<tr>
							<td><?php echo $row3['id_cat'] ?></td>
							<td>__ <?php echo utf8_encode($row3['cat_title']) ?></td>
							<td><?php echo $row3['cat_parent'] ?></td>
							<td>__ <?php echo $row3['cat_order'] ?></td>
						</tr>
						<?php
					} ?>
			<?php } ?>
			<?php endforeach; ?>
		</tbody>
	</table>
	<?php  ?>
</body>
</html>


Hasta ahí todo funciona muy bien, el detalle es que la consulta sigue siendo estático, porque no sabemos cuantas categorías y sub categorías habrán anidadas dentro de las mismas.

Ahora mismo el código anterior hace consultas solamente a dos niveles pero me gustaría que se haga a N niveles sin importar de cuantas categorías y sub .... sub categorías ingrese el usuario.

La idea es que dicha consulta se muestre igual al listado de categorías de Wordpress.

Siento mucho si no me dejo entender, aportes por favor. Gracias

NOTA: La conexión a la base de datos es muy básica, sólo para cuestiones pedagógicas.
Tags: Database - HTML - MySQL - PHP - PHP Advanced - utf-8 - Virtualization - VPS - VPS Linux - Wikipedia Votes: 0 - Answers: 7 - Views: 15 Share on: Google Facebook Twitter LinkedIn Link
 

Answers:

  • Date: 20-05-2019 12:35:45 Puedes hacer una funcion recursiva y tienes todos al momento...

    Ejemplo seudocodigo de la funcion:

    funcion regresacate(numcatebuscar) {
    seleccionado = selecciona campos donde cat_paren=numcatebuscar
    si seleccionado entonces
    comienza recorrer
    regresacate(recorrer.identificador)
    en caso contrario entonces
    regreso false;

    }


    y asi obtendras todos... cada uno a los que pertenecen y dentro los que contienen...

    O al presentar que sea selects dependientes...
    Seudocodigo:
    Selecciono categoria
    Buscar y crear selec si tiene subcategorias
    si hay subcategorias, selecciono sub
    Buscar si hay subcategoria de sub
    busco si hay subcategoria y creo select...
    etc


    Esto con ayuda de ajax.

    Ejemplo selects dinamicos aqui ya solo debes controlar con la cantidad que necesites....

    Saludos....
    Stryfe™
      Votes: 1 - Link answer
     
  • Date: 20-05-2019 16:23:46 Un abrazo amigo Ernesto muchas gracias por su respuesta, es muy bueno lo que me sugieres, no se me había ocurrido antes mil gracias una vez más, por lo pronto he implementado lo que usted me ha indicado y quedó asi.
    <?php
    	function consulta($id) {
    		$cn = mysqli_connect("localhost", "root", "", "prueba_db");
    		$sql = mysqli_query($cn, "SELECT * FROM categorias WHERE cat_parent = '$id' ORDER BY cat_order asc");
    		if (mysqli_num_rows($sql) > 0) {
    			$value = '';
    			foreach ($sql as $row) {
    				$value .= '<tr>
    										<td>' . $row['id_cat'] . '</td>
    									 	<td>' . utf8_encode($row['cat_title']) . '</td>
    										<td>' . $row['cat_parent'] . '</td>
    										<td>' . $row['cat_order'] . '</td>
    									</tr>';
    				$value .= consulta($row['id_cat']);
    			}
    		}
    		return $value;
    	}
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    	<title>PRUEBA CONSULTA</title>
    	<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" title="all" />
    </head>
    <body>
    	<table class="table table-bordered" style="max-width: 600px; margin: 20px auto">
    		<thead>
    			<tr>
    				<th>ID</th>
    				<th>Title</th>
    				<th>Parent</th>
    				<th>Order</th>
    			</tr>
    		</thead>
    		<tbody>
    			<?php echo consulta(0); ?>
    		</tbody>
    	</table>
    </body>
    </html>

    Ciertamente hay que mejorar en el aspecto visual pero eso ya es cosa secundaria, aquí dejo el código y también abierta la pregunta por si a alguien le sirve y/o aportar algo más al respecto.
      Votes: 0 - Link answer
     
  • Date: 21-05-2019 04:43:09 Con la función recursiva vas a andar bien, pero puede darte problemas de rendimiento (Exige mucho a la base principalmente).

    Hay una nueva funcionalidad que se agregó más o menos recientemente a MySQL que puede mejorar mucho el tema, fijate en: http://www.mysqltutorial.org/mysql-adjacency-list-tree/

    Otra cosa que podrías buscar es una representación diferente del árbol de categorías (Se conoce como conjunto anidado). Fijate este ejemplo: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
      Votes: 0 - Link answer
     
  • Date: 21-05-2019 13:08:30 Saludos amigo Mauro, justo me estoy documentando por lo que me has compartido y créeme que está muy interesante, justo lo que estuve buscando. Muchas gracias, un abrazo.   Votes: 0 - Link answer
     
  • Date: 21-05-2019 14:41:07 Saludos Mauro y David
    Pues al final es un recursivo el SQL
    y el detalle (y no es por ofender David) pero si una funcion sencilla no la manejo, imaginate una directa en SQL. Ademas fue si no puede modificar la tabla.

    Aun asi esta bien que te documentes David, pues al final nadie nace sabiendo y nunca se deja de aprender...

    Asi mismo, si puedes modificar la tabla es mejor agregar nivel, asi te quitas de muchos sql, haciendo un simple:

    SELECT campos FROM tabla where depende=numero order by campoNivel

    Saludos a ambos... Y por cierto Mauro, me mandas un mensaje al chat de gmail.. nos hechamos una platicadita...

    Stryfe™
      Votes: 0 - Link answer
     
  • Date: 21-05-2019 15:04:24 Un abrazo Ernesto, descuida por lo de la documentación son para fines didácticos la idea es probar posibilidades y también la idea central de ésta pregunta es que se pueda potenciar los conocimientos.

    Si no se experimenta no se aprende "Existen muchos caminos para llegar a la cima". Gracias a ustedes Ernesto y Mauro por su interés en el caso, sigamos potenciando nuestras experiencias. Saludos amigos.
      Votes: 0 - Link answer
     
  • Date: 22-05-2019 05:20:55 Gracias David! (Puedes ponerle un voto positivo a la respuesta si te resultó útil ;)   Votes: 0 - Link answer
     
To actively participate in the community first must authenticate, enter the system.Sign In