PHP menu en submenu in dezelfde tabel?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Donald Boers

Donald Boers

23/06/2017 20:26:42
Quote Anchor link
Ik heb een main menu bestaande uit 8 records. Van deze 8 records hebben er 3 ook sub items (submenu) Er is mij vaak verteld om volgens een structuur te werken waar zowel de main items als de sub items in dezelfde database tabel staan gebruikmakend van parent_id. Iets zoals dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE `menus` (
  `id` int(11) NOT NULL,
  `menu_name` varchar(32) NOT NULL,
  `parent_id` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `menus` (`id`, `menu_name`, `parent_id`) VALUES
(1, 'Home', 0),
(2, 'About us', 0),
(3, 'Services', 0),
(4, 'Contact', 0),
(5, 'Online Service', 3),
(6, 'Home Service', 3);

Op zich klinkt het heel logisch maar ik heb geen idee hoe ik hier mee om moet gaan in mijn Model (query), View (Template) en Controller. Ik werk namelijk via het MVC principe. Kan iemand mij een stap op weg helpen.

Bij voorbaat dank
 
PHP hulp

PHP hulp

27/04/2024 07:23:49
 
Frank Nietbelangrijk

Frank Nietbelangrijk

23/06/2017 21:49:22
Quote Anchor link
Met twee slimmigheidjes los je dat in PHP op.
1) stop de menu items die bij elkaar horen in een array (doe print_r($menu) om te zien wat ik bedoel)
2) maak een recursive functie die zichzelf herhaaldelijke keren aanroept en zo het menu maakt

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php

/*
 * example data
 */

$data = array(
    array(
        'id' => 1,
        'name' => 'homepage',
        'parent' => 0
    ),
    array(
        'id' => 2,
        'name' => 'About',
        'parent' => 0
    ),
    array(
        'id' => 3,
        'name' => 'Services',
        'parent' => 0
    ),
    array(
        'id' => 4,
        'name' => 'Contact',
        'parent' => 0
    ),
    array(
        'id' => 5,
        'name' => 'Online Service',
        'parent' => 3
    ),
    array(
        'id' => 6,
        'name' => 'Home Service',
        'parent' => 3
    ),
    array(
        'id' => 7,
        'name' => 'test',
        'parent' => 6
    ),
);



$menu = array();

/*
 * use array keys to sort the menu items
 */

foreach($data as $item)
{

    $menu[$item['parent']][] = $item;
}


// print_r($menu);

echo buildMenu($menu);

/*
 * Recursive function that creates submenus in other submenus
 */

function buildMenu($menu, $key = 0)
{

    $html = '<ul>' . "\n";
    
    foreach($menu[$key] as $item)
    {

        $html .= '<li>' . $item['name'];

        if(isset($menu[$item['id']])) {
            $html .= buildMenu($menu, $item['id']);
        }


        $html .= '</li>' . "\n";
    }

    $html .= '</ul>' . "\n";
    
    return $html;
}


?>
 
Donald Boers

Donald Boers

23/06/2017 22:01:03
Quote Anchor link
Hoi Frank. :)

Hartelijk bedankt voor de reactie. Dat ziet er logisch uit. Maar hoe query ik de database?
 
Frank Nietbelangrijk

Frank Nietbelangrijk

23/06/2017 22:10:00
Quote Anchor link
vervang regel 1 t/m 54 voor:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$menu
= array();
$query = 'SELECT * FROM menu';
$result = mysqli_query($conn, $query);
while($item = mysqli_fetch_assoc($result)) {
    $menu[$item['parent']][] = $item;
}
Gewijzigd op 23/06/2017 22:11:33 door Frank Nietbelangrijk
 
Donald Boers

Donald Boers

23/06/2017 22:42:20
Quote Anchor link
Hi Frank. Wederom bedankt!

Het probleem is dat, zoals ik al aangaf via MVC methode werk. Dus ik heb dit in mijn Model
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
public function get_menu()
{
    $sql = "SELECT *
              FROM menu";
                  
    $stmt = $this->pdo->query($sql);        
    return $stmt->fetchAll();
}


Dit pik ik op in de Controller:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$menu_items = $this->page->get_menu();


en verstuur dit naar de Vieuw:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$this->render('header', compact('menu_items'));


Met andere woorden, waar jij de opmaak in je functie(s) hebt doe ik dat normaal gesproken in de View:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php foreach($menu_items as $menu_item): ?>
   ......
<?php endforeach; ?>


En op dit punt weet ik niet hoe ik jou methode hierin zou moeten verwerken.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

23/06/2017 23:03:46
Quote Anchor link
Donald,

De MVC methode is enkel bedoeld om verantwoordelijkheden onder te verdelen waardoor je programma beter gestructureerd wordt.

Het renderen van de menu items zou ik niet in de view doen (als uitzondering op de rest) vanwege de complexe geneste structuur. In plaats daarvan zou je je eigen class moeten bouwen die meer opties biedt dan mijn voorbeeldje. Minimaal zou je in je data ook een css-class mee moeten kunnen geven en natuurlijk ook de link.
Maar je kunt ook nog denken aan een icon, een "active" menu-item en aan disabled menu items :-)

In je controller zou je dan iets kunnen doen als
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php

$menu
= new MyCustomMenu(); // je eigen class
$menu->initialize($this->page->get_menu());

$this->render('header', array(
    'menu' => $menu
));
?>


en in de view zou je dan kunnen doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
echo $menu->render();
?>


Toevoeging op 23/06/2017 23:22:37:

Voorzetje voor MyCustomMenu:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php

class MyCustomMenu
{
    protected $menu;

    public function initialize($menu_items)
    {

        foreach($menu_items as $item)
        {

            $this->menu[$item['parent']][] = $item;
        }

            
        return $this;
    }


    public function render()
    {

        return $this->buildMenu($this->menu);
    }


    /*
     * Recursive function that creates submenus in other submenus
     */

    protected function buildMenu($menu, $key = 0)
    {

        $html = '<ul>' . "\n";
    
        foreach($menu[$key] as $item)
        {

            $html .= '<li>' . $item['name'];

            if(isset($menu[$item['id']])) {
                $html .= $this->buildMenu($menu, $item['id']);
            }


            $html .= '</li>' . "\n";
        }


        $html .= '</ul>' . "\n";
    
        return $html;
    }
}
Gewijzigd op 23/06/2017 23:49:14 door Frank Nietbelangrijk
 
Donald Boers

Donald Boers

24/06/2017 13:06:41
Quote Anchor link
Hoi Frank, wederom hartelijk bedankt voor de input. Ik ga hiermee aan de slag
 
Donald Boers

Donald Boers

19/07/2017 07:31:53
Quote Anchor link
Hoi Frank.

Sorry voor een beetje late reactie. Afgelopen week in de lappemand gelegen (snip en snip verkouden). Even terugkomend op deze kwestie. Er zijn een aantal dingen die mij verwarren. Allereerst je hebt het over een complexe geneste structuur, maar zo complex is het eigenlijk toch niet. Er zijn twee levels. 1 met parent_id = NULL en 1 met parent_id = 2 dan wel 3. Ik heb jou methode proberen na te maken in de voor mij bekende werkwijze:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public function get_menu_items($lang)
{
    $sql = "SELECT *
              FROM menu
             WHERE language_abbr = ?";
                
    $items = $this->pdo->prepare($sql);
    $items->execute(array($lang));
        
    $menu_items = array();
    foreach ($items as $item) {
        if (!isset($menu_items[$item['parent_id']])) {
            $menu_items[$item['parent_id']] = array();    
        }
        $menu_items[$item['parent_id']][] = $item;
                
    }
    return $menu_items;        
}


en dit in de View:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<ul>
<?php $parent_id = NULL; foreach ($menu_items[$parent_id] as $item):?>
<li><a href="#"><?= $item['navigation_name']; ?></a></li>    
<?php endforeach; ?>
</ul>

Dit geeft me in principe al de eerste laag (parent_id = NULL). Er is een andere reden waarom ik het een en ander wel graag in de View doe en wel om de reden dat de site Bootstrap based is dus ik ook nog wel wat classes etc kwijt moet (dropdown etc).

Ben alleen niet zeker hoe ik de tweede laag (sub menus) moet genereren
Gewijzigd op 19/07/2017 07:44:10 door Donald Boers
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.