Adjacency Model Ik krijg het niet voor elkaar

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Innovatieve, nauwkeurige Senior PHP Developer voor

Eind jaren ’90 is dit bedrijf opgericht. Ze hebben zich altijd beziggehouden met het ontwikkelen van software voor overheidsinstanties. Dit zijn instanties waaronder bijvoorbeeld ook onder andere : de belastingdienst, burgerszaken, verschillende bedrijven, notarissen, incassobureau’s en ook nog bewindvoerders. Momenteel tellen ze 20 medewerkers, waarvan 2/3 deel allemaal developers zijn. Doordat ze de enigste aanbieder van dit soort software op de markt zijn, groeien ze erg hard. Door de enorme groei, hebben ze dan ook concrete groeiplannen in het verschiet. Functie-omschrijving Het bedrijf wordt door allerlei instanties ingeschakeld. Tegenwoordig wordt alles digitaal geregeld en gezien de essentie van dit soort

Bekijk vacature »

Donald Boers

Donald Boers

13/08/2018 11:53:18
Quote Anchor link
Ik ondervind problemen met het maken van een Adjacency list. Voorheen gebruikte ik altijd if statements in de View voor het opmaken van een multi level menu. Maar daar ik via het MVC principe probeer te werken hoort dat natuurlijk niet zo. Dus heb ik gisteren verschillende tutorial gelezen over dit onderwerp. maar ik kom er niet uit Dit is de tafel:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
CREATE TABLE IF NOT EXISTS `navigatie` (
  `id` tinyint(4) NOT NULL AUTO_INCREMENT,
  `parent` tinyint(4) NOT NULL DEFAULT '0',
  `url` varchar(64) NOT NULL,
  `label` varchar(64) NOT NULL,
  `sequence` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Dit is de inhoud:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
INSERT INTO `navigatie` (`id`, `parent`, `url`, `label`, `sequence`) VALUES
(1, 0, '/', 'Home', 1),
(2, 0, 'javascript:void(0)', 'Diensten', 2),
(3, 0, 'avascript:void(0)', 'Tarieven', 3),
(4, 0, '/case_studies', 'Case Strudies', 4),
(5, 0, '/over', 'Over', 5),
(6, 2, '/diensten/online_strategie', 'Online Strategie', 1),
(7, 2, '/diensten/webdesign', 'Web Design', 2),
(8, 2, '/diensten/webdevelopment', 'Web Development', 3),
(9, 2, '/diensten/digital_marketing', 'Digital Marketing', 4);


En in de Model Class heb ik het volgende:
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
    public function get_menu()
    {
        $sql = $this->pdo->query('SELECT * FROM site_navigation ORDER BY parent, sequence ASC');
        
        $items    = array();
        $rows = $sql->fetchAll(PDO::FETCH_ASSOC);
        foreach ($rows as $r => $row) {
            $parent = (int)$row['parent'];
            if (!isset($items[$parent])) {
                $items[$parent][] = $row;
            }
        }
        foreach ($items[0] as $m => $item) {
            echo '<ul class="navbar-nav ml-auto">';
                echo '<li>'.$item['label'].'</li>';
                $this->get_sub_menu($item['id']);
            echo '</ul>';
        }
        return $items;
    }


En dan loop ik vast. Kan iemand mij verder op weg helpen. Bij voormaat dank
Gewijzigd op 13/08/2018 12:00:37 door Donald Boers
 
PHP hulp

PHP hulp

22/09/2018 02:25:43
 
Thomas van den Heuvel

Thomas van den Heuvel

13/08/2018 13:43:43
Quote Anchor link
Lijkt veel op deze recente thread, lees die eens door voor mogelijke inspiratie.
 
Donald Boers

Donald Boers

13/08/2018 14:40:39
Quote Anchor link
@Thomas. Het klink misschien heel dom maar ik zie de overeenkomst niet. Zou je op basis wat ik in de openings post heb gedeeld een voorbeeld kunnen geven?

Alvast bedankt
 
Thomas van den Heuvel

Thomas van den Heuvel

13/08/2018 19:51:37
Quote Anchor link
De query zal in ieder geval op de tabel "navigatie" moeten plaatsvinden, of hoe je deze ook uiteindelijk noemt, dit is mogelijk niet "site_navigation"?

Verder zou je de bewerkingen kunnen splitsen in:
- het bouwen van de boom
- het printen van de boom

Ik denk dat het onderstaande standalone voorbeeld voor zich spreekt:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php
// https://www.phphulp.nl/php/forum/topic/adjacency-model-ik-krijg-het-niet-voor-elkaar/102341
/*
CREATE TABLE IF NOT EXISTS `navigatie` (
  `id` tinyint(4) NOT NULL AUTO_INCREMENT,
  `parent` tinyint(4) NOT NULL DEFAULT '0',
  `url` varchar(64) NOT NULL,
  `label` varchar(64) NOT NULL,
  `sequence` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

// mind the typo in Tarieven
INSERT INTO `navigatie` (`id`, `parent`, `url`, `label`, `sequence`) VALUES
(1, 0, '/', 'Home', 1),
(2, 0, 'javascript:void(0)', 'Diensten', 2),
(3, 0, 'javascript:void(0)', 'Tarieven', 3),
(4, 0, '/case_studies', 'Case Strudies', 4),
(5, 0, '/over', 'Over', 5),
(6, 2, '/diensten/online_strategie', 'Online Strategie', 1),
(7, 2, '/diensten/webdesign', 'Web Design', 2),
(8, 2, '/diensten/webdevelopment', 'Web Development', 3),
(9, 2, '/diensten/digital_marketing', 'Digital Marketing', 4);
*/

error_reporting(E_ALL);
ini_set('display_startup_errors', true);
ini_set('display_errors', 'stdout');

class Test
{
    protected $db;
    protected $tree;

    public function __construct() {
        $this->db = new mysqli('ip', 'user', 'password', 'db');
        $this->db->set_charset('utf8'); // never forget!
        $this->buildTree(); // init tree
    }

    protected function buildTree() {
        // dummy root element
        $this->tree = array(
            0 => array(
                'label'     => 'root',
                'url'       => '',
                'parent'    => false,
                'children'  => array(),
            ),
        );


        $res = $this->db->query(
            'SELECT id, parent, url, label
            FROM navigatie
            ORDER BY parent, sequence'

        );
        while ($row = $res->fetch_assoc()) {
            // init current element
            $this->tree[$row['id']] = array(
                'label'     => $row['label'],
                'url'       => $row['url'],
                'parent'    => $row['parent'],
                'children'  => array(),
            );

            // hook current element to parent
            $this->tree[$row['parent']]['children'][] = $row['id'];
        }
    }
// buildTree

    protected function escape($in) {
        return htmlspecialchars($in, ENT_QUOTES, 'UTF-8');
    }
// escape

    public function printTree($id=0) {
        // print current item, except if it is root
        $item = $this->tree[$id]; // shorthand
        if ($id > 0) {
            // always use some form of output escaping!
            ?>
<li><a href="<?php echo $this->escape($item['url']) ?>"><?php echo $this->escape($item['label']) ?></a><?php
        }
        // does this item have children?
        if (count($item['children']) > 0) {
            ?>
<ul><?php
                foreach ($item['children'] as $child) {
                    $this->printTree($child);
                }

            ?>
</ul><?php
        }
        // close current item
        if ($id > 0) {
            ?>
</li><?php
        }
    }
// printTree
} // Test

$test = new Test();
$test->printTree();
?>
[end]
 
Donald Boers

Donald Boers

14/08/2018 00:35:38
Quote Anchor link
@Thomas. Dat ziet er geweldig uit, hartelijk dank hiervoor. Laatste vraagje nog. Zoals ik al aangaf probeer ik via de MVC methode te werken, dus mijn vraag is hoe ik dit (printTree) naar de Controller krijg en dus vervolgens in de View kan gebruiken

Toevoeging op 14/08/2018 07:56:46:



Toevoeging op 14/08/2018 08:12:58:

@Thomas. Dit is mijn Controller:
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
class Controller
{
    protected $pageId;
    protected $tuinId;
    protected $layout = 'layout';
    protected $page;

    public function __construct()
    {
        $pdo            = Db::getInstance();
        $this->page     = new Model_Page($pdo);
    }

    protected function render($template, $data = array())
    {
        $layoutData = array(
            'main_items'      => $this->page->get_main_menu(),
            'sub_items'       => $this->page->get_sub_menu(),
            'content'         => new View($template.'.php', $data)
        );
        $view = new View($this->layout.'.php', array_merge($layoutData, $data));
        echo $view->render();
    }
}


Kan ik dat gedeelte vanaf protected function buildTree() onder de construct__ functie toevoegen? Ik bedoel:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
$this->pdo->set_charset('utf8');
$this->buildTree();

toevoegen aan de construct functie en het gedeelte vanaf de buildTree() functie daaronder plaatsen?
Sorry voor mijn onwetendheid maar ik heb werkelijk geen idee.
Gewijzigd op 14/08/2018 08:14:31 door Donald Boers
 
Thomas van den Heuvel

Thomas van den Heuvel

14/08/2018 14:30:16
Quote Anchor link
Ik denk dat je het als volgt moet zien. MVC schrijft je theoretisch voor hoe je dingen organiseert. Het zou waarschijnlijk logisch zijn als je het opbouwen van de (data van de) boom regelt in een Model. Vervolgens zorgt een View voor de weergave hiervan. Maar dan zit je met de Controller.

Een webpagina is opgebouwd uit meerdere onderdelen: een kop, wat menu's, wat sidebars en andere snippets, en dan een brok hoofd content en dan misschien nog wat footers en fluff. Alles is vaak gecentreerd rondom die hoofdcontent en dat (lijkt mij althans) is dan ook waar de Controller rondom gecentreerd zal zijn: welke content wordt op die pagina geserveerd. Mogelijk hebben menu's wel wat interactie met de pagina in de vorm van een gehighlighte link van de huidige pagina, of een uitgeklapt submenu van het onderdeel waar je in zit.

De vraag is echter, hoe past dat in MVC? Hier is volgens mij geen eenduidig antwoord op, althans, ik heb deze nooit echt gevonden. Dit is meer een soort van systeemarchitectuurvraag - hoe regel ik de opbouw van mijn webpagina's, en tegelijkertijd probeer je waarschijnlijk MVC te doorgronden en dit concept toe te passen :).

Mijn (voorzichtige) advies zou zijn: maakt het jezelf niet te moeilijk. Neem voorlopig genoegen een MVC-aanpak voor de hoofdcontent, en organiseer ondertussen alle "randfunctionaliteit" zoals menu's en sidebars zo goed als dat kan en zinnig is in op zijn minst classes en templates.

Daarnaast zijn er misschien ook nog wel andere logische eenheden te onderscheiden (zoals het Maintemplate, het skelet van je webpagina, waarin dit menu en alle andere "randcontent" min of meer verankerd zit)?

Mogelijk kun je dat later nog wel helemaal ombouwen naar een soort van hiërarchische MVC (volgens mij heette dat ook echt zo HMVC) maar blijf je zelf afvragen: ben ik nu niet het paard achter de wagen aan het spannen door mezelf het gereedschap op te leggen waarmee ik de klus zou moeten klaren?

Ik heb ook redelijk wat informatie gezocht over wat MVC nu precies is en hoe dit er in de praktijk uit zou moeten zien. Die zoektocht werd aanzienlijk bemoeilijkt door ... ahem ... hardliners die daar ... uitgesproken meningen over hebben :). Hierbij is het waarschijnlijk belangrijk (zoals ook een van de comments zei, geloof ik) dat MVC een idee (jaja, design pattern) is, met vele uitwerkingsvormen / verschijningen.
 
Ward van der Put
Moderator

Ward van der Put

14/08/2018 14:54:26
Quote Anchor link
Verschijningsvormen zoals Model-View-Presenter (MVP) voor GUI's, bijvoorbeeld:

https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Model_View_Presenter_GUI_Design_Pattern.png/220px-Model_View_Presenter_GUI_Design_Pattern.png
 
Donald Boers

Donald Boers

15/08/2018 07:18:00
Quote Anchor link
Thomas van den Heuvel op 14/08/2018 14:30:16:
Ik denk dat je het als volgt moet zien. MVC schrijft je theoretisch voor hoe je dingen organiseert. Het zou waarschijnlijk logisch zijn als je het opbouwen van de (data van de) boom regelt in een Model. Vervolgens zorgt een View voor de weergave hiervan. Maar dan zit je met de Controller.

Een webpagina is opgebouwd uit meerdere onderdelen: een kop, wat menu's, wat sidebars en andere snippets, en dan een brok hoofd content en dan misschien nog wat footers en fluff. Alles is vaak gecentreerd rondom die hoofdcontent en dat (lijkt mij althans) is dan ook waar de Controller rondom gecentreerd zal zijn: welke content wordt op die pagina geserveerd. Mogelijk hebben menu's wel wat interactie met de pagina in de vorm van een gehighlighte link van de huidige pagina, of een uitgeklapt submenu van het onderdeel waar je in zit.

De vraag is echter, hoe past dat in MVC? Hier is volgens mij geen eenduidig antwoord op, althans, ik heb deze nooit echt gevonden. Dit is meer een soort van systeemarchitectuurvraag - hoe regel ik de opbouw van mijn webpagina's, en tegelijkertijd probeer je waarschijnlijk MVC te doorgronden en dit concept toe te passen :).

Mijn (voorzichtige) advies zou zijn: maakt het jezelf niet te moeilijk. Neem voorlopig genoegen een MVC-aanpak voor de hoofdcontent, en organiseer ondertussen alle "randfunctionaliteit" zoals menu's en sidebars zo goed als dat kan en zinnig is in op zijn minst classes en templates.

Daarnaast zijn er misschien ook nog wel andere logische eenheden te onderscheiden (zoals het Maintemplate, het skelet van je webpagina, waarin dit menu en alle andere "randcontent" min of meer verankerd zit)?

Mogelijk kun je dat later nog wel helemaal ombouwen naar een soort van hiërarchische MVC (volgens mij heette dat ook echt zo HMVC) maar blijf je zelf afvragen: ben ik nu niet het paard achter de wagen aan het spannen door mezelf het gereedschap op te leggen waarmee ik de klus zou moeten klaren?

Ik heb ook redelijk wat informatie gezocht over wat MVC nu precies is en hoe dit er in de praktijk uit zou moeten zien. Die zoektocht werd aanzienlijk bemoeilijkt door ... ahem ... hardliners die daar ... uitgesproken meningen over hebben :). Hierbij is het waarschijnlijk belangrijk (zoals ook een van de comments zei, geloof ik) dat MVC een idee (jaja, design pattern) is, met vele uitwerkingsvormen / verschijningen.

@Thomas. Dat is geen antwoord op mijn vraag. Ik heb je de Controller getoond. Dus de vraag blijft. Kan ik jou oplossing in mijn Controller integreren? Dat is het enige dat ik graag zou willen weten. Anders blijf ik mijn oude systeem hanteren
 
Rob Doemaarwat

Rob Doemaarwat

15/08/2018 09:15:08
Quote Anchor link
Volgens mij zegt Thomas hier met heel veel woorden: zie maar (er is niet 1 "juiste" manier). Dus zoals je het nu gedaan hebt is een (prima) oplossing.

Zelf neig ik wat meer naar de "hard liners" toe, en zou ik alleen de hiërarchische layoutData meegeven (dus de data uit $this->tree in Thomas z'n voorbeeld), en de werkelijke HTML uitwerking in je (HTML) template doen. In mijn eigen geval iets van:
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
//in main template
<!--
  toon voor alle items in mainMenu de volgende regel
  (incl subMenu via tekst blok "subMenu")
-->
<ul class="main-menu">
[*mainMenu|<li><a href='\[url\]'>\[label\]</a>\[@subMenu\]</li>]
</ul>

//en tekst blok "subMenu" is dan:
<!--
  indien children, toon alle children
  en indien die weer children, enz
-->
{[%children]{<ul class="sub-menu">
[*children|<li><a href='\[url\]'>\[label\]</a>\[@subMenu\]</li>]
</ul>}}


Voordeel hiervan is dat je "later" de menu data ook heel eenvoudig via bijvoorbeeld een JSON view mee kunt geven aan een API ofzo (mocht je een app gaan maken die wel dezelfde menu structuur gaat gebruiken, maar deze zelf rendert - vanuit die JSON data).
Gewijzigd op 15/08/2018 09:17:08 door Rob Doemaarwat
 
Thomas van den Heuvel

Thomas van den Heuvel

15/08/2018 15:04:08
Quote Anchor link
Ik bedoelde meer dat een menu een onderdeel is van een groter geheel, en dat het misschien logischer is om op dat grotere geheel het MVC-patroon toe te passen, en niet op elke snippet.

Quote:
Dat is geen antwoord op mijn vraag.

Misschien niet, maar ik probeer je attent te maken op wat nuances, en dat je misschien wat aan het doorslaan bent met waar en wanneer je MVC zou moeten toepassen.

Los daarvan, dit klinkt nogal ondankbaar. Ik krijg niet betaald om jouw problemen op te lossen en ik wil je ook niet direct een (rechtstreekse) oplossing geven, want dan sta je morgen weer voor de deur met iets waar je niet voldoende over na hebt gedacht. Ik wil dat je nadenkt over wat je doet zodat je er op een gegeven moment zelf uit kunt komen.

Daarbij, stel dat jij het moeras inrijdt, moet ik je dan aanmoedigen en uitleggen hoe je beste kunt vermijden dat je niet vast komt te staan in de blubber, of zou het toch handiger zijn je te wijzen op een verharde weg? Ik snap dat jij zo snel mogelijk naar je bestemming wilt, maar er moet wel een weg lopen. Soms moet je terug om vooruit te kunnen.

Jij vraagt om advies, en vervolgens zeg je in wezen "dit antwoord / deze aangewezen oplossingsrichting bevalt me niet". Mja. Good luck.
 
Donald Boers

Donald Boers

15/08/2018 15:13:59
Quote Anchor link
@Thomas. Het is absoluut geen ondankbaarheid. Ik vraag alleen of hetgeen jij als voorbeeld gaf in mijn huidige Controller kan worden geïntegreerd. Ik vraag je niet om een complete website te maken, ik vraag je niet om op basis van wat ik heb getoond het af te maken zodat ik het kan het kan kopiëren en plakken. Ik vraag alleen of het mogelijk is om hetgeen je als voorbeeld gaf in mijn huidige Controller te integreren.

Sorry dat je het verkeerd hebt begrepen
 
Thomas van den Heuvel

Thomas van den Heuvel

15/08/2018 15:32:45
Quote Anchor link
Ik zal er vast helemaal naast zitten but here goes:
De Controller bepaalt welke hoofdcontent er geladen dient te worden.
De hoofdcontent zit vaak in een (main)template.
Dit (main)template bevat allerlei snippets, waaronder het bovenstaande menu.

Mijn eerste ingeving zou dan ook zijn: de Controller is niet de plek waar je zaken omtrent dit menu regelt. Dit is niet (direct) de verantwoordelijkheid van de Controller. Ik zou haast zeggen dat dit wordt bepaald door de hoofdcontent zelf.

But who am I to blow against the wind.
 
Donald Boers

Donald Boers

15/08/2018 15:38:38
Quote Anchor link
@Thomas. In ieder geval bedankt. Inderdaad doet iedereen dingen op zijn eigen manier. Even goede vrienden
 
Bart V B

Bart V B

19/08/2018 09:43:35
Quote Anchor link
Ik ben het eens met Thomas.
Een controller is in mijn ogen een knooppunt waar alles bij elkaar komt.
Een model haalt heel de meuk bij elkaar.
En een view bouwt het geheel op het scherm.

De class van Thomas is dan ook best sterk gemaakt, hij weet niets van wat hij moet uitpoepen dus kan uitbereid worden, immers kan het ook zijn dat je ooit iets van XMl of JSON ooit wil gebruiken.
En dat kan makkelijk met die class. (Zou hem alleen een andere naam geven)

Ik weet natuurlijk niet of dit een enkel project is of dat je dit voor meerdere wil inzetten?

Dus mijn idee zou zijn om dit in template code te doen.
Immers dan word het al geladen door de controller.

Maar in een controller zelf niet. Iets met DRY. ;) (Don't repeat Yourself)
 



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.