Publicidad

Como crear un menú desplegable en PHP, HTML, CSS y javascript / jquery


Por Alex el 11/07/2023, Comentar el artículo

Comparte este artículo:      




En este artículo explico como crear un menú de dos niveles en PHP basado en dos tabla en MySql. La idea es muy sencilla con dos tablas almacenamos el menú y el contenido correspondiente a cada menú. Esta en PHP nativo pero utilizarse el código con cualquier framework e incluso es sencillo traspasar a otro lenguaje.


Por ejemplo creamos un menú de ejemplo como si fuera un curso de MySql. El resultado final del menú desplegable es el siguiente:

Resultado final menú desplegable

Los pasos que a seguir son los siguientes:



En github dejo el repo del proyecto https://github.com/depruebas/menu-desplegable-php

Y aquí están los scripts para crear la tabla y las consultas que crean los menús https://github.com/depruebas/menu-desplegable-php/tree/master/sql que acontinuación explico.


Crear menú en base de datos

Lo primero que hacemos es crear los registros del menú en la base se datos, primero los del nivel principal que serán los títulos del menú, en el ejemplo serán los títulos de los cursos

	INSERT INTO `menus` (`parent_id`, `name`, `alias`, `enabled`, `orden`, `created_at`) 
		VALUES ('0', 'MySql en Linux', NULL, '1', '1', CURRENT_TIMESTAMP);
	INSERT INTO `menus` (`parent_id`, `name`, `alias`, `enabled`, `orden`, `created_at`) 
		VALUES ('0', 'MySql en Windows', NULL, '1', '1', CURRENT_TIMESTAMP);


Para relacionar los menús utilizamos el campo parent_id que para los títulos de los cursos es 0 y para las lecciones que componen el curso será el id. Por ejemplo las lecciones que pertenecen al curso de MySql en Linux si el id del curso es 1 será el parent_id:

	INSERT INTO `menus` (`parent_id`, `name`, `alias`, `enabled`, `orden`, `created_at`) 
		VALUES ('1', 'Información general', NULL, '1', '1', CURRENT_TIMESTAMP);
	INSERT INTO `menus` (`parent_id`, `name`, `alias`, `enabled`, `orden`, `created_at`) 
		VALUES ('1', 'Guías de inicio rápido', NULL, '1', '5', CURRENT_TIMESTAMP);
	INSERT INTO `menus` (`parent_id`, `name`, `alias`, `enabled`, `orden`, `created_at`) 
		VALUES ('1', 'Tutoriales', NULL, '1', '15', CURRENT_TIMESTAMP);
	INSERT INTO `menus` (`parent_id`, `name`, `alias`, `enabled`, `orden`, `created_at`) 
		VALUES ('1', 'Recursos', NULL, '1', '10', CURRENT_TIMESTAMP);


Ahora hay que crear las lecciones que las pondremos en la otra tabla menus_contenido

	-- Temas correspondientes al menú Información general
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('3', 'Novedades', 'Breve sobre las novedades', 'Texto sobre las novedades', '1', '1', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('3', 'Notas de la versión', 'BREVE sobre Notas de la versión',' TEXTO sobre Notas de la versión', '1', '5', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('3', 'Historial de versiones', 'Breve sobre Historial de versiones', 'Texto sobre Historial de versiones', '1', '10', CURRENT_TIMESTAMP, NOW());

	-- Temas correspondientes al menú Guías de inicio rápido
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('4', 'Instalación en SUSE', 'BREVE sobre Instalación en SUSE', 'TEXTO sobre Instalación en SUSE', '1', '1', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('4', 'Instalación en Red Hat', 'BREVE sobre Instalación en Red Hat', 'TEXTO sobre Instalación en Red Hat', '1', '5', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('4', 'Instalación en Ubuntu', 'BREVE sobre Instalación en Ubuntu', 'TEXTO sobre Instalación en Ubuntu', '1', '10', CURRENT_TIMESTAMP, NOW());

	-- Temas correspondientes al menú Tutoriales
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('5', 'Novedades de la documentación de MySql', 'BREVE sobre documentación', 'TEXTO sobre documentación', '1', '1', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('5', 'Migración desde Windows', 'BREVE sobre Migración desde Windows', 'TEXT sobre Migración desde Windows', '1', '1', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('5', 'Migración desde docker', 'BREVE Migración desde docker', 'TEXTO sobre Migración desde docker', '1', '5', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('5', 'Novedades en los recursos', 'BREVE sobre Novedades en los recursos', 'TEXTO sobre Novedades en los recursos', '1', '10', CURRENT_TIMESTAMP, NOW());
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('5', 'Novedades en los recursos', 'BREVE sobre Novedades en los recursos', 'TEXTO sobre Novedades en los recursos', '1', '15', CURRENT_TIMESTAMP, NOW());

		-- Temas correspondientes al menú Recursos
	INSERT INTO `menus_contenido` (`menu_id`, `title`, `brief`, `text`, `enabled`, `orden`, `created_at`, `updated_at`) 
		VALUES ('6', 'Guia de solución de problemas', 'BREVE sobre solución de problemas', 'TEXTO sobre solución de problemas', '1', '1', CURRENT_TIMESTAMP, NOW());




Listar menús desde base de datos con PHP

Ahora que tenemos la base de datos creada con las tablas y los menús insertados vamos a crear una página index.php para leer con una consulta SQL ese menú. La consulta es la siguiente:

select m.id as menu_id, m.name as menu_name, 
    mm.id as submenu_id, mm.name as submenu_name, mm.orden as submenu_orden,
      mc.id as tema_id, mc.title as tema_title, mc.orden as tema_orden
      from menus as m
      inner join menus as mm On m.id = mm.parent_id
      inner join menus_contenido as mc On mc.menu_id = mm.id
      where m.id = 1
      order by mm.orden asc, mc.orden asc;


Y el resultado de esta consulta es el siguiente:

Resultado consulta menú desplegable

En este listado tenemos:
  • menu_name titulo del menú
  • submenu_name los títulos de los submenus
  • tema_name los títulos dentro de los submenus



Código PHP y javsacript para crear el menú desplegable

Una vez tenemos la consulta preparada la ejecutamos en el código PHP de la siguiente forma:

$db = mysqli_connect("172.21.0.2", "root", "root", "ejemplo_menus", 3306);

$rows = $db->query( "select m.id as menu_id, m.name as menu_name, 
    mm.id as submenu_id, mm.name as submenu_name, mm.orden as submenu_orden,
      mc.id as tema_id, mc.title as tema_title, mc.orden as tema_orden
      from menus as m
      inner join menus as mm On m.id = mm.parent_id
      inner join menus_contenido as mc On mc.menu_id = mm.id
      where m.id = 1
      order by mm.orden asc, mc.orden asc;")
  ->fetch_all(MYSQLI_ASSOC);


El resultado de la consulta devolverá n registros en un array con esta estructura:

Array ( [0] => Array ( [menu_id] => 1 [menu_name] => MySql en Linux [submenu_id] => 3 [submenu_name] => Información general [submenu_orden] => 1 [tema_id] => 2 [tema_title] => Novedades [tema_orden] => 1 ) ... ... )

Y este array lo recorreremos con el siguiente código PHP para crear el menú en html


$submenu = '';  

for( $i = 0; $i < count( $rows); $i++)
{   

  if ( $submenu != $rows[$i]['submenu_id'])
  {
    echo '<li class="list-unstyled">';
    echo '<a id=Submenu_'.$rows[$i]['submenu_id'].' href="#" data-toggle="collapse" aria-expanded="false" class="">
      <i class="fa-solid fa-circle fa-0xs"></i>'.$rows[$i]['submenu_name'].'</a>';
    echo '<ul class="collapse " id="pageSubmenu_'.$rows[$i]['submenu_id'].'">';
  }

  echo '<li class="list-unstyled"><a href="/class/'.$rows[$i]['tema_id'].'"><i class="fa fa-chevron-right mr-2 fa-0xs"></i>'.$rows[$i]['tema_title'].'</a></li>';

  $submenu = $rows[$i]['submenu_id'];

  if ( $submenu != $rows[$i+1]['submenu_id'])
  {
    echo '</ul></li>';
  }
  
}


Y este será el resultado hasta ahora:

Resultado menú sin desplegar

Pero nos faltan un par de cosas, hasta ahora tenemos el menú pero no es desplegable, para poder desplegar el siguiente nivel y acceder a los temas hay que crear el código javascript/jquery y una consulta más que nos dará el numero de submenus tenemos que activar.

El código javascript es el siguiente:


window.onload = function() {
    
    let menus = [<?php echo $menus[0]['ids']; ?>];

    console.log(menus);
    console.log(menus.length);

    for (let i = 0; i < menus.length; i++)
    {
      console.log( menus[i]);
      $("#Submenu_" + menus[i]).click(function(){

        event.preventDefault();

        if ( !$('#pageSubmenu_' + menus[i]).is(':visible')) 
        {
          $("#pageSubmenu_" + menus[i]).show();
          
          for (let j = 0; j < menus.length; j++)
          {
            if ( menus[i] != menus[j])
            {
              $("#pageSubmenu_" + menus[j]).hide();
            }
          }
         
        } 
        else 
        {
          $("#pageSubmenu_" + menus[i]).hide();
        }

      });

    }

  };


Y la consulta del numero de menus que almacenamos en la variable PHP, $menus y que se recoge en el código Javascritp es:

$menus = $db->query( "select GROUP_CONCAT(id SEPARATOR ', ') as ids from menus where parent_id = 1")
->fetch_all(MYSQLI_ASSOC);


Y hasta aquí el ejemplo de menú desplegable.

Todo el código esta en el repositorio https://github.com/depruebas/menu-desplegable-php

Al final son dos consultas SQL, un poco de código PHP y Javascript/jquery que se puede trasladar a cualquier framework, incluso en otros lenguajes.

Y esto es todo, feliz programming
Saludos
Alex.



Si te ha gustado el artículo compartelo en:      




Añadir un comentarios:

Nombre:
Email: (no se publica el email)




SIGUENOS EN

ARCHIVO

Publicidad

.