Foros del Web » Programando para Internet » PHP »

Menú dinamico en mvc

Estas en el tema de Menú dinamico en mvc en el foro de PHP en Foros del Web. Hola compañeros aca con una duda, estoy desarrollando un menú que traigo de la BD, por ahora lo tengo en un solo archivo y lo ...
  #1 (permalink)  
Antiguo 06/04/2017, 21:40
 
Fecha de Ingreso: octubre-2011
Mensajes: 132
Antigüedad: 12 años, 6 meses
Puntos: 4
Menú dinamico en mvc

Hola compañeros aca con una duda, estoy desarrollando un menú que traigo de la BD, por ahora lo tengo en un solo archivo y lo necesito separar en modelo-vista-controlador, el gran problema con el que me encontre es que tiene una funcion recursiva y por ahi no se como llamarlo en la vista aca les dejo lo que tengo por si alguien me de una idea.

esta es la BD:
Código SQL:
Ver original
  1. CREATE TABLE IF NOT EXISTS `menu` (
  2.   `id` INT(11) NOT NULL AUTO_INCREMENT,
  3.   `id_parent` INT(11) NOT NULL DEFAULT '0',
  4.   `link` VARCHAR(255) NOT NULL,
  5.   `order` INT(11) NOT NULL DEFAULT '0',
  6.   `title` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_polish_ci NOT NULL DEFAULT '',
  7.   `level` tinyint(4) NOT NULL DEFAULT '0',
  8.   PRIMARY KEY (`id`)
  9. ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=24 ;
  10.  
  11.  
  12.  
  13. INSERT INTO `menu` (`id`, `id_parent`, `link`, `order`, `title`, `level`) VALUES
  14. (12, 0, '', 0, 'Office Furniture', 0),
  15. (13, 12, '', 0, 'Chairs', 0),
  16. (14, 12, '', 0, 'Work Tables', 0),
  17. (15, 12, '', 0, 'Workstations', 0),
  18. (16, 12, '', 0, 'Storage', 0),
  19. (17, 12, '', 0, 'Conference Tables', 0),
  20. (18, 13, '', 0, 'with spagh', 0),
  21. (19, 13, '', 0, 'without spagh', 0),
  22. (20, 18, '#', 0, 'Triangle', 0),
  23. (21, 18, '#', 0, 'Sqare', 0),
  24. (22, 19, '#', 0, 'Simple', 0),
  25. (23, 19, '#', 0, 'Complex', 0);

Y este el script php:
Código PHP:

$db 
= new PDO('mysql:dbname=db_menu''root''123456',
array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

function 
createsubmenu($item)
{
    global 
$db;
    
$subsel $db->prepare('SELECT id, link, title, level  FROM menu WHERE id_parent = :parent ORDER BY `order`');

    
$subsel->execute(array('parent' => $item));
    
$text '';

        foreach (
$subsel as $i) {

        
$text .= '<li class="menucolor' . ($i['level'] - 1) . '">'
            
.'<a href="' htmlspecialchars($i['link']) . '">' htmlspecialchars($i['title']) . '</a>'
            
createsubmenu($i['id']) . '</li>';
        }

    if (
$text == '') {
        return 
'';
    }

    return 
'<ul id="red" class="treeview-red">' $text '</ul>';
}

echo 
createsubmenu(0); 
Gracias de antemano por su tiempo y ayuda.
  #2 (permalink)  
Antiguo 10/04/2017, 19:26
 
Fecha de Ingreso: octubre-2011
Mensajes: 132
Antigüedad: 12 años, 6 meses
Puntos: 4
Respuesta: Menú dinamico en mvc

Ningun alma bondadosa que me ayude con alguna idea?
  #3 (permalink)  
Antiguo 10/04/2017, 23:15
 
Fecha de Ingreso: julio-2014
Mensajes: 334
Antigüedad: 9 años, 9 meses
Puntos: 30
Respuesta: Menú dinamico en mvc

Las almas estás pero quizás no en el momento cuando las necesitamos jejejeje

Tu problema es que aún no estás concibiendo el funcionamiento del patrón MVC. Desde las vistas no se llaman a las funciones, ni tienen lógica incrustada. Eso se realiza desde los controladores y desde ahí se pasan los resultados a las vistas, que por eso lo llaman "vista".

Después tienes que obtener primero todos los menús padres, recorrerlos y conseguir de cada uno los hijos para imprimirlos y ya.

Yo lo haría de este modo:

Código PHP:
Ver original
  1. #El siguiente código se debe de colocar en el controlador correspondiente dentro de la función que le corresponda que en este caso podría ser index() dentro del HomeController por poner un ejemplo de controlador.
  2.  
  3. # Primero, creo una función para ejecutar todas mis consultas a la base de datos, recuerda la siguiente norma: una función ha de contener UNA sola función, de este modo, consigues, además, poder reutilizar el mismo código sin tener que repetir una y otra vez las mismas lineas por cada consulta
  4. function _exectueQuery($sql, $values) {
  5.     global $db;
  6.     $subsel = $db->prepare($sql);
  7.  
  8.     return $subsel->execute($values);
  9. }
  10.  
  11. function getParentMenus() {
  12.     $sql = "SELECT id, link, title, level FROM menu ORDER BY title";
  13.  
  14.     #Ejecutamos la consulta y obtenedremos todos los menús padres
  15.    return _exectueQuery($sql, $data);
  16. }
  17.  
  18. function getChildMenus($item) {
  19.     $sql = "SELECT id, link, title, level FROM menu WHERE id_parent = :parent ORDER BY title";
  20.  
  21.     #Ejecutamos la consulta y obtenedremos todos los menús hijos
  22.    return _exectueQuery($sql, $data);
  23. }
  24.  
  25. # Esta función te retorna el menú ya construido
  26. function getMenus()
  27. {
  28.     $html = '';
  29.     # Conseguimos los menús padres
  30.    $menus = getParentMenus();
  31.  
  32.     #Primero recorremos los menus padres para colocarlos dentro del menu
  33.    $html .= createsMenu($menus);
  34.  
  35.     return $html;  
  36. }
  37.  
  38. # Y aquí la función de recursividad, donde consultará todos los niveles habidos y por haber dentro de una matriz multidimensional o en tu caso, los menús.
  39. function createsMenu($menus, $color = '')
  40. {  
  41.     # Tendrás que pasar como parametro el color del menú para poder hacerlo dinámico
  42.    $html = '<ul id="' . $color . '"class="treeview-' . $color . '">';
  43.  
  44.     foreach ($menus as $menu) {
  45.         #NO entiendo la parte de tu código ($i['level'] -1), si el valor de level es 0, no puede ser -0. Por eso lo dejé como lo hago ahora
  46.  
  47.         #Creamos la primera lista pero no lo cerramos todavía
  48.        $html .= '<li class="menucolor-' . $color . '"><a href="' . htmlspecialchars($menu['link']) . '">' . htmlspecialchars($menu['title']) . '</a>';
  49.  
  50.         # Comprobamos si el actual menú tiene hijos
  51.        $childs = getChildMenus($menu['id']);
  52.  
  53.         # Si los tiene, los recorremos para imprimirlos dentro del menú en curso, de lo contrario, cerramos <li></li>
  54.        $html .= count($childs) > 0? createsMenu($childs) : '</li>';
  55.     }
  56.  
  57.     # Cerramos la lista si ya no hay más registros
  58.    $html .= '</ul>';
  59.  
  60.     return $html;
  61. }

Una vez que tengas toda la lógica en el controlador, cuando llames a la vista pasandole el parámetro $html tendrías que tener algo como:
Código HTML:
Ver original
  1. <!DOCTYPE html>
  2.     <title>Tu app</title>
  3. </head>
  4.     <nav><?=$html ?></nav>
  5.  
  6. </body>
  7. </html>

Como ves, no he hecho uso de ninguna lógica de php para obtener el resultado, solo le paso el parametro a la vista ya.

Espero que te sirva en un futuro, he decidido darte esta pequeña clase, ya que otros no han sabido aplicar bien las explicaciones por entregarles pseudo-codigo a algiuen que está comenzando. Así te lo entrego de una vez, lo aprendes y ya no se te va a olvidar.

OJO! No lo he probado pero debería de funcionarte, si algo te sale mal, te garantizo que el fallo te saldrá dentro de la función createsMenu(); es muy probable que me haya podido confundir en los lugares que imprimo cada sección del html.
  #4 (permalink)  
Antiguo 11/04/2017, 08:00
Avatar de vb2005  
Fecha de Ingreso: noviembre-2005
Ubicación: Paderborn - Alemania
Mensajes: 566
Antigüedad: 18 años, 5 meses
Puntos: 24
Respuesta: Menú dinamico en mvc

Cita:
Iniciado por Triby2 Ver Mensaje
Las almas estás pero quizás no en el momento cuando las necesitamos jejejeje

Tu problema es que aún no estás concibiendo el funcionamiento del patrón MVC. Desde las vistas no se llaman a las funciones, ni tienen lógica incrustada. Eso se realiza desde los controladores y desde ahí se pasan los resultados a las vistas, que por eso lo llaman "vista".

Después tienes que obtener primero todos los menús padres, recorrerlos y conseguir de cada uno los hijos para imprimirlos y ya.

Yo lo haría de este modo:

Código PHP:
Ver original
  1. #El siguiente código se debe de colocar en el controlador correspondiente dentro de la función que le corresponda que en este caso podría ser index() dentro del HomeController por poner un ejemplo de controlador.
  2.  
  3. # Primero, creo una función para ejecutar todas mis consultas a la base de datos, recuerda la siguiente norma: una función ha de contener UNA sola función, de este modo, consigues, además, poder reutilizar el mismo código sin tener que repetir una y otra vez las mismas lineas por cada consulta
  4. function _exectueQuery($sql, $values) {
  5.     global $db;
  6.     $subsel = $db->prepare($sql);
  7.  
  8.     return $subsel->execute($values);
  9. }
  10.  
  11. function getParentMenus() {
  12.     $sql = "SELECT id, link, title, level FROM menu ORDER BY title";
  13.  
  14.     #Ejecutamos la consulta y obtenedremos todos los menús padres
  15.    return _exectueQuery($sql, $data);
  16. }
  17.  
  18. function getChildMenus($item) {
  19.     $sql = "SELECT id, link, title, level FROM menu WHERE id_parent = :parent ORDER BY title";
  20.  
  21.     #Ejecutamos la consulta y obtenedremos todos los menús hijos
  22.    return _exectueQuery($sql, $data);
  23. }
  24.  
  25. # Esta función te retorna el menú ya construido
  26. function getMenus()
  27. {
  28.     $html = '';
  29.     # Conseguimos los menús padres
  30.    $menus = getParentMenus();
  31.  
  32.     #Primero recorremos los menus padres para colocarlos dentro del menu
  33.    $html .= createsMenu($menus);
  34.  
  35.     return $html;  
  36. }
  37.  
  38. # Y aquí la función de recursividad, donde consultará todos los niveles habidos y por haber dentro de una matriz multidimensional o en tu caso, los menús.
  39. function createsMenu($menus, $color = '')
  40. {  
  41.     # Tendrás que pasar como parametro el color del menú para poder hacerlo dinámico
  42.    $html = '<ul id="' . $color . '"class="treeview-' . $color . '">';
  43.  
  44.     foreach ($menus as $menu) {
  45.         #NO entiendo la parte de tu código ($i['level'] -1), si el valor de level es 0, no puede ser -0. Por eso lo dejé como lo hago ahora
  46.  
  47.         #Creamos la primera lista pero no lo cerramos todavía
  48.        $html .= '<li class="menucolor-' . $color . '"><a href="' . htmlspecialchars($menu['link']) . '">' . htmlspecialchars($menu['title']) . '</a>';
  49.  
  50.         # Comprobamos si el actual menú tiene hijos
  51.        $childs = getChildMenus($menu['id']);
  52.  
  53.         # Si los tiene, los recorremos para imprimirlos dentro del menú en curso, de lo contrario, cerramos <li></li>
  54.        $html .= count($childs) > 0? createsMenu($childs) : '</li>';
  55.     }
  56.  
  57.     # Cerramos la lista si ya no hay más registros
  58.    $html .= '</ul>';
  59.  
  60.     return $html;
  61. }

Una vez que tengas toda la lógica en el controlador, cuando llames a la vista pasandole el parámetro $html tendrías que tener algo como:
Código HTML:
Ver original
  1. <!DOCTYPE html>
  2.     <title>Tu app</title>
  3. </head>
  4.     <nav><?=$html ?></nav>
  5.  
  6. </body>
  7. </html>

Como ves, no he hecho uso de ninguna lógica de php para obtener el resultado, solo le paso el parametro a la vista ya.

Espero que te sirva en un futuro, he decidido darte esta pequeña clase, ya que otros no han sabido aplicar bien las explicaciones por entregarles pseudo-codigo a algiuen que está comenzando. Así te lo entrego de una vez, lo aprendes y ya no se te va a olvidar.

OJO! No lo he probado pero debería de funcionarte, si algo te sale mal, te garantizo que el fallo te saldrá dentro de la función createsMenu(); es muy probable que me haya podido confundir en los lugares que imprimo cada sección del html.
Es un error de concepto que tu "controlador" genere código html

No hay que confundir la lógica a hacer un loop en un array de elementos para generar una lista de elementos en html.

Es totalmente correcto hacer un for dentro de la vista para imprimir asi los elementos.

Tu código tiene todo acumulado en un sólo método que lo hace todo, ese no es el objetivo de MVC
__________________
www.marcher.com.uy - Web personal
Nerd's Corner - Desarrollo de software a medida
  #5 (permalink)  
Antiguo 11/04/2017, 10:16
 
Fecha de Ingreso: julio-2014
Mensajes: 334
Antigüedad: 9 años, 9 meses
Puntos: 30
Respuesta: Menú dinamico en mvc

Cita:
Iniciado por vb2005 Ver Mensaje
Es un error de concepto que tu "controlador" genere código html

No hay que confundir la lógica a hacer un loop en un array de elementos para generar una lista de elementos en html.

Es totalmente correcto hacer un for dentro de la vista para imprimir asi los elementos.

Tu código tiene todo acumulado en un sólo método que lo hace todo, ese no es el objetivo de MVC
Yo no dije, que el controlador genere odigo html, es uan locura. Lo que dije, es LLAMAR...

"Una vez que tengas toda la lógica en el controlador, cuando llames a la vista pasandole el parámetro $html tendrías que tener algo como"

Y si, se puede ejecutar un loop como for o foreach en la vista, pero no mucho mas de ahi, pues esos loops solo deben de ser para mostrar los datos del array.

Lo que el compañero pretendia hacer, es llamar a una funcion desde la vista... y encima dentro de un <li>
  #6 (permalink)  
Antiguo 11/04/2017, 11:47
 
Fecha de Ingreso: octubre-2011
Mensajes: 132
Antigüedad: 12 años, 6 meses
Puntos: 4
Respuesta: Menú dinamico en mvc

Hola triby2 gracias por responder, estuve probando el codigo y me surgieron algunas dudas con respecto a las consultas que se hace en el controlador, estas no deberian estar en el modelo me refiero a las consultas function getParentMenus() y getChildMenus($item), trate de ponerlas en el modelo como siempre lo hago de esta manera:

Código SQL:
Ver original
  1. public FUNCTION getParentMenus()
  2.     {
  3.         $menu = $this->_db->query('SELECT id, link, title, level FROM meno ORDER BY title');
  4.         RETURN $menu->fetchAll();
  5.     }

Y en el controlador llamo al modelo de esta manera

Código PHP:
class indexController extends Controller
{
    private 
$_menu;

    public function 
__construct()
    {
        
parent::__construct();
        
$this->_menu $this->loadModel('index');
    } 
y en una funcion traigo los datos para despues renderizarlo en la vista
de esta manera:

Código PHP:
public funcion index(){

//asi traigo los datos del modelo
$this->_view->menu $this->_menu->getParentMenus(); 

//asi renderizo a la vista
$this->_view->renderizar('index''inicio'); 

Y en la vista mostraba los datos con un foreach.

hice modificaciones pero sin ningun resultado positivo :(
  #7 (permalink)  
Antiguo 12/04/2017, 09:25
Avatar de vb2005  
Fecha de Ingreso: noviembre-2005
Ubicación: Paderborn - Alemania
Mensajes: 566
Antigüedad: 18 años, 5 meses
Puntos: 24
Respuesta: Menú dinamico en mvc

Cita:
Iniciado por Triby2 Ver Mensaje
Yo no dije, que el controlador genere odigo html, es uan locura. Lo que dije, es LLAMAR...

"Una vez que tengas toda la lógica en el controlador, cuando llames a la vista pasandole el parámetro $html tendrías que tener algo como"

Y si, se puede ejecutar un loop como for o foreach en la vista, pero no mucho mas de ahi, pues esos loops solo deben de ser para mostrar los datos del array.

Lo que el compañero pretendia hacer, es llamar a una funcion desde la vista... y encima dentro de un <li>
El problema es que en tu código están todos los conceptos mezclados.

En el mismo lugar hay responsabilidades del modelo, controlador y vista en el mismo lugar/método.

Tu vista lo único que tiene es un "echo $html" eso muestra de que hay responsabilidades que no fueron repartidas correctamente, porque el encargado de generar el html es la vista y no el controlador
__________________
www.marcher.com.uy - Web personal
Nerd's Corner - Desarrollo de software a medida
  #8 (permalink)  
Antiguo 16/04/2017, 07:46
 
Fecha de Ingreso: julio-2014
Mensajes: 334
Antigüedad: 9 años, 9 meses
Puntos: 30
Respuesta: Menú dinamico en mvc

Cita:
Iniciado por vb2005 Ver Mensaje
El problema es que en tu código están todos los conceptos mezclados.

En el mismo lugar hay responsabilidades del modelo, controlador y vista en el mismo lugar/método.

Tu vista lo único que tiene es un "echo $html" eso muestra de que hay responsabilidades que no fueron repartidas correctamente, porque el encargado de generar el html es la vista y no el controlador
Lo puse asi expresamente, si esta aprendiendo mvc, lo suyo es que aprenda diferenciar donde va cada funcion. Y mi vista es UN EJEMPLO...
  #9 (permalink)  
Antiguo 16/04/2017, 07:59
 
Fecha de Ingreso: julio-2014
Mensajes: 334
Antigüedad: 9 años, 9 meses
Puntos: 30
Respuesta: Menú dinamico en mvc

Cita:
Iniciado por stevens82 Ver Mensaje
Hola triby2 gracias por responder, estuve probando el codigo y me surgieron algunas dudas con respecto a las consultas que se hace en el controlador, estas no deberian estar en el modelo me refiero a las consultas function getParentMenus() y getChildMenus($item), trate de ponerlas en el modelo como siempre lo hago de esta manera:

Código SQL:
Ver original
  1. public FUNCTION getParentMenus()
  2.     {
  3.         $menu = $this->_db->query('SELECT id, link, title, level FROM meno ORDER BY title');
  4.         RETURN $menu->fetchAll();
  5.     }

Y en el controlador llamo al modelo de esta manera

Código PHP:
class indexController extends Controller
{
    private 
$_menu;

    public function 
__construct()
    {
        
parent::__construct();
        
$this->_menu $this->loadModel('index');
    } 
y en una funcion traigo los datos para despues renderizarlo en la vista
de esta manera:

Código PHP:
public funcion index(){

//asi traigo los datos del modelo
$this->_view->menu $this->_menu->getParentMenus(); 

//asi renderizo a la vista
$this->_view->renderizar('index''inicio'); 

Y en la vista mostraba los datos con un foreach.

hice modificaciones pero sin ningun resultado positivo :(
Bueno, el codigo ya lo tienes, y resuelve tu problema de recursividad, lo que hay que trabajar ahora es el resultado.

Es normal que el resultado no sea el esperado pues el codigo no lo probé. ¿podrias compartir el resultado de mi codigo?

En cuanto tus dudas, en el modelo solo se deberia de guardar los metodos para añadir, actualizar, leer y borrar registros de la tabla.

En el controlador, van todas las funciones que te compartí, y ademas las funciones basicas que llamarian a los metodos de añadir, actualizar, leer y borrar pasanxoles a vada uno de ellos los datos a tratar. Es decir,en el contro,ador, crearias el array de datos que necesitas manejar, y pasarias el array al meteodo que necesites para que el modelo lo trate, una vez eso, llamarias a la vista.

Jamas llames a la vista desde el metodo constructor del controlador, pues no es lo correcto, lo suyo es que tengas un metodo index que SI llamaria a la vista para mostrar los datos, despues tendrias un metodo store(), donde recibiria los datos de un formulario, por poner un ejemplo, crearia el array como tu lo necesites, y lo enviarias al modelo para guardarlo, despues llamarias a la vista que podria mostrar un mensaje confirmando que se guardo, por poner un ejemplo.

Tendrias otro metodo llamado edit() que obtendria los datos del registro para mostrarlo en el formulario para que el usuario lo pueda editar y al clicar guardar,llamarias al metodo update() del controlador, que montaria el array con los datos modificados para ser enviado el metodo de actualizar en el modelo, despues llamaria a una vista que podria contener el menaje de que se actualizo con exito.

¿me explico?

Etiquetas: bd, dinamico, html, mvc, select, sql
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 19:59.