Menu klasse

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

.NET developer

Functie The position we have for you As a .NET developer you will work for one of our customers active in the High Tech Industry. Our customers are mainly located in the Eindhoven area. We are very selective when it comes to the projects we accept and therefore only focus on innovative and complex projects. Because our customers are mainly specialized in machine construction, you often work close to the machines. Our team currently consists of Embedded engineers, IOT developers and Cloud engineers. We mainly work on Microsoft projects where WPF, UWP, .NET Core and Microsoft Azure are used. Eisen

Bekijk vacature »

Freelance JAVA / C# Developer

Functieomschrijving Ben je een ervaren freelancer of werk je in loondienst en ben je toe aan een nieuwe uitdaging? Lees dan snel verder want wie weet is dit een leuke vacature voor jou! Voor een opdrachtgever in omgeving Delft zijn wij op zoek naar ervaren JAVA of C# Developers die graag op projectbasis willen werken. Je komt terecht bij een informele developers club die mooie projecten uitvoeren voor grote klanten. Het fijne van deze werkgever is dat je zelf mag beslissen hoe je te werk wilt gaan. Wil je als freelancer werken dan is dat OK. Wil je de zekerheid

Bekijk vacature »

.Net developer

Sogeti is een organisatie met een goede werksfeer en zo min mogelijk hiërarchische verhoudingen. Ga je bij ons als .Net Developer aan de slag? Dan werk je dagelijks met collega’s aan de mooiste IT-projecten. Deze snelgroeiende groep collega’s krijgt energie van hun vak en dat merk je op de werkvloer. Natuurlijk krijg jij de mogelijkheid je te certificeren. We organiseren regelmatig technische Meet-ups en doen we veel aan kennisdeling. Mede hierdoor zij wij dit jaar Microsoft Partner of the year geworden. Sogetisten staan klaar voor elkaar, hebben lol met elkaar en daarmee behalen we de mooiste resultaten! Werken bij Sogeti

Bekijk vacature »

Senior Cobol Applicatieontwikkelaar

Bedrijfsomschrijving De IV- organisatie van de Belastingdienst is verantwoordelijk voor en verzorgt de ICT- voorzieningen. Het merendeel van de applicaties wordt op dit moment door de IV- organisatie zelf ontwikkeld, onderhouden en beheerd in het eigen data center. Naast de zorg voor continuïteit op de massale heffing- en inningsprocessen die plaatsvinden binnen een degelijke, stabiele omgeving, wordt er tevens volop gewerkt aan modernisering van het IV- landschap. Dit gebeurt deels intern door gebruik te maken van de expertise die intern aanwezig is, maar ook door het aantrekken van (kant-en-klaar) oplossingen en expertise uit de markt. Functieomschrijving In de applicatie ETM

Bekijk vacature »

Front-end Developer Angular

Dit ga je doen Jouw taken als Front End Developer bestaan uit: Het ontwikkelen van maatwerkoplossingen voor klanten; Het meedenken over nieuwe tools en technieken; Het begeleiden van junioren; Het meewerken aan diverse projecten; Het meedenken in UX/UI design. Hier ga je werken Als Front-End Developer ga je in een Scrum team aan de slag met de nieuwste digitale technologieën om klanten en overheden over de hele wereld te ondersteunen met het ondersteunen van hun software, veelal op het gebied van watermanagement en infra. Door middel van real-time data in combinatie met voorspellende analyses, AI, Deep Learning en Machine Learning

Bekijk vacature »

PHP Developer

As a PHP Developer at Coolblue, you ensure that our webshops work as optimal as possible. How do I become a PHP Developer at Coolblue? As a PHP Developer you work together with other development teams to make our webshop work as optimal as possible and to make our customers happy. Although you are a PHP Developer, you are not averse to a little TypeScript or other technologies that might be used. Would you also like to become a PHP Developer at Coolblue? Read below if the job suits you. You enjoy doing this Writing vanilla PHP code. Working with

Bekijk vacature »

Software developer - senior

Functie omschrijving Voor een echt softwarebedrijf in omgeving Gouda zijn wij op zoek naar versterking voor de afdeling Software Development! Ben jij op zoek naar een werkgever waar meerdere software developers werken aan interessante projecten? Ben jij op zoek naar een werkgever waar je onderdeel wordt van een team dat echt passie heeft voor het ontwikkelen van software? Dan ben je hier aan het juiste adres! Als softwareontwikkelaar kom je terecht bij een onafhankelijk, door kwaliteit gedreven, doortastend en daarbij op een Agile wijze werkend bedrijf. Ben jij een expert in het vertalen van Componenten van Functionaliteit naar Business lagen?

Bekijk vacature »

Fullstack of back-end PHP developer

Functie Ieder onderdeel van de software draait op aparte servers en het bestaat dus echt uit verschillende componenten. Het team bestaat uit 4 developers, een klein team dus met korte lijnen. Alles in intern ontwikkeld en je werkt aan alle facetten. Van uitbreiding van de core tot maatwerk voor de klant. Ook liggen er verschillende uitdagingen op servervlak en databases. Je zult de eerste periode veel samenwerken met de lead developer om vervolgens echt je gang te gaan binnen de software. In het team streven ze naast de hoogst haalbare kwaliteit. Hiervoor werken ze nauw met elkaar samen en levert

Bekijk vacature »

C# .NET Developer

Functie omschrijving Ben jij op zoek naar een nieuwe uitdaging binnen development waar je komt te werken binnen een flexibel, jong en ondernemend bedrijf. Lees dan snel verder! Voor deze functie zoeken wij een C# .NET Developer die enthousiast wordt van het aansluiten en begeleiden van (complexe) nieuwe klanten. Daarnaast begeleid je complexe projecten, wij zoeken iemand die altijd kansen ziet en waarbij het glas altijd half vol is. Voor deze functie zoeken wij een Developer met ervaring op het gebied van .NET die deze organisatie gaat versterken. Binnen de organisatie ga jij je vooral bezighouden met het verbeteren van

Bekijk vacature »

Full stack .NET developer Microsoft 365

Wat ga je doen als Full stack .NET developer Microsoft 365? Je stelt je op als sparringpartner voor het team en PO over toekomstige functionaliteiten, architectuur en mogelijke nieuwe producten. Je bent mede-verantwoordelijk voor het vertalen en omzetten van een user story in een passend technisch design. Je implementeert functionaliteiten op basis van een technisch design en user story. Je bent mede-verantwoordelijk voor het beheer van Azure DevOps, waaronder het beheer van GIT, Build Pipelines, Release Pipelines en geautomatiseerde testen. Hier herken jij jezelf in Hbo werk- en denkniveau of hoger aangevuld met relevante certificeringen en/of cursussen; Minimaal 3 jaar

Bekijk vacature »

Oracle APEX developer

Wat je gaat doen: Als Oracle APEX ontwikkelaar bij DPA werk je samen met collega’s aan de meest interessante opdrachten. Je zult je ervaring met SQL, PL/SQL, JavaScript, HTML en CSS inzetten om wensen van opdrachtgevers te vertalen naar technische oplossingen. Je werk is heel afwisselend, omdat DPA zich niet beperkt tot een specifieke branche. Zo ben je de ene keer bezig binnen de zorgsector, de andere keer is dit bij de overheid. Wat we vragen: Klinkt goed? Voor deze functie breng je het volgende mee: Je hebt een hbo- of universitaire opleiding afgerond Je hebt 2 tot 5 jaar

Bekijk vacature »

.NET Developer C# VB

Samengevat: Deze werkgever is actief in software voor het matchen van vraag en aanbod van gebruikte auto-onderdelen. Ben jij een .NET Developer? Heb je ervaring met het ontwikkelen (REST) en integreren van webservices? Vaste baan: C# .NET Developer C# VB HBO €2.600 - €6.200 Wij ontwikkelen software om vraag en aanbod van onderdelen van personenauto's bij elkaar te brengen. Deze werkgever is een veelzijdige organisatie. Je werkt voor de eigen IT organisatie. Zij werken met moderne technologie en staan open voor innovatie. De branche van dit bedrijf is Automotive. Functie: Voor de vacature als .NET Developer Dordrecht HBO ga je

Bekijk vacature »

Als Lead PHP developer bijdragen aan het onderwijs

Functie Als Lead PHP developer zet je samen met het team en de andere lead developers de technische lijnen uit als het gaat om het ontwikkelen van de applicaties en bepaal je samen met de PO waar elke sprint aan gewerkt zal worden. Je kunt op basis van een user story een goede aanpak formuleren en een planning opstellen, en andere hierin meenemen. Wanneer je team code schrijft verwacht je degelijke oplossingen, bij voorkeur gebruik makend van Domain Driven Design. Je ziet toegevoegde waarde in het beoordelen van het werk van collega’s om zo samen te streven naar hoge kwaliteit

Bekijk vacature »

PHP Developer

Functieomschrijving Vanuit het hoofdkantoor in omgeving Roosendaal, ontwikkel je als PHP Developer niet alleen webapplicaties, maar ben je verder ook gefocust op het continu inspelen op nieuwe trends en ontwikkelingen m.b.t software development. Naast het bouwen van webapplicaties, ontwikkelen zij ook webshops en websites voor gave opdrachtgevers! Wat ga je doen? Het schrijven van schone en efficiënte codes volgens het Symfony framework; Het ontwerpen en implementeren van webapplicaties met het Symfony-framework; Onderhouden en updaten van bestaande applicaties die zijn gebouwd met het Symfony framework; Het testen van ontwikkelde applicaties om te zorgen dat ze goed functioneren en voldoen aan de

Bekijk vacature »

Robot Programmeur

In het kort Drie redenen waarom deze vacature uniek is! Programmeren van zelflerende robots Werken op kantoor en testen in de bedrijfshal Je krijgt verantwoordelijkheid, vrijheid en je mag werken naar eigen inzicht De organisatie Hier ga je aan de slag Een bedrijf dat innovatieve robottoepassingen ontwerpt en bouwt voor onder andere de staal industrie, energie- bouw- en agrarische sector. De robots die vaak in combinatie met diverse randapparatuur geleverd worden vormen een totaaloplossing voor de klant. Dit zijn klanten over de hele wereld, van België en Duitsland tot China, India, maar ook in Nederland. Projecten waar momenteel aan wordt

Bekijk vacature »
Tom Swinkels

Tom Swinkels

04/03/2012 21:30:06
Quote Anchor link
Beste Phpers,

Ik wil een menu klasse gaan schrijven, de bedoeling is dat het menu uit de database komt. Er kunnen ook sub-menu's zijn.

Nu zat ik zelf te denken aan een menu klasse.

klasse Menu:

-setName($name)
-setUrl($url)
-setParentId($parentid)
-setId()
-getName() (array)
-getUrl() (array)
-getParentId (array)
-getId() (array)

klasse MenuMapper:

-getMenu() (haalt het menu uit de database en maakt de klasse menu aan)

Ik vroeg me af of dit een goede opzet is, en hoe ik verder alle gets bij elkaar kan voegen aangezien alles los word opgeslagen van 1 menu item?
 
PHP hulp

PHP hulp

21/11/2024 20:49:29
 
Wouter J

Wouter J

04/03/2012 21:54:45
Quote Anchor link
Ik zou het nog 1 keer verder verdelen en ook een Menu_item klasse gebruiken:

Menu_list
# items = array()
# rol = ''
+ constructor( array $items = array(), $rol = 'primary' )
+ addItem( $item )
+ removeItem( $id )

Menu_item
# url
# name
+ constructor( $name, $url )
+ setName( $name )
+ setUrl( $url )
+ getName( $name )
+ getUrl( $url )
+ __toString()

Dan kun je ook veel makkelijker submenu's maken:
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
<?php
$menu
= new Menu_list();

// normale menu items
$menu->addItem( new Menu_item('Home', '/home') );
$menu->addItem( new Menu_item('About', '/about') );

// submenu's
$menu->addItem( new Menu_list(array(
  new
Menu_item('Foo', '/category/1/foo'),
  new
Menu_item('Bar', '/category/2/bar'),
  new
Menu_item('Lorem', '/category/3/lorem'),
)) );

?>
 
Tom Swinkels

Tom Swinkels

04/03/2012 22:02:30
Quote Anchor link
Oke, dit is opzicht wel duidelijk maar je kunt natuurlijk ook alles in een array gooien? En daarna de array verdelen/sorteren? ParentId = 0 wil namelijk zeggen dat het een menu is, wanneer het geen 0 is zal dat het id van het hoofd menu zijn.

Hoe wil jij het op jou manier uit de database halen? Want aan jou voorbeeld kan ik niet zien bij welk menu de sub-items horen?

Verder geef jij in je voorbeeld $name en $url mee aan de __contruct, waarom heb je dan nog een setName() en setUrl() methode?
 
Wouter J

Wouter J

04/03/2012 22:08:33
Quote Anchor link
Quote:
dit is opzicht wel duidelijk maar je kunt natuurlijk ook alles in een array gooien? En daarna de array verdelen/sorteren?

Ja, maar dan moet je alsnog werken met een menu item klasse. Want je hebt nu gewoon properties die niet bij het menu object horen. Als id, parent_id, url, name. Dat zijn allemaal eigenschappen van een menu item en niet van een menu.
Dus als je alles in een array stopt heb je minder OO en wordt de klasse meer een verzameling functies (wat ook niet slecht is, maar dan is het geen OO meer).

Quote:
Hoe wil jij het op jou manier uit de database halen? Want aan jou voorbeeld kan ik niet zien bij welk menu de sub-items horen?

Dat is ook een probleem waaraan ik zat te denken. Je zou een Menu_item Mapper moeten maken, maar misschien ook een Menu_list Mapper.

Quote:
Verder geef jij in je voorbeeld $name en $url mee aan de __contruct, waarom heb je dan nog een setName() en setUrl() methode?

De naam en de url zijn eigenschappen die je nodig hebt voor het correct werken van een klasse. Vandaar dat ze aan de constructor meegegeven worden.
Maar omdat in OO alles draait om flexibiliteit zitten er ook nog aparte setters in, zodat je halverwege het script de url/name kunt wijzigen.
 
Tom Swinkels

Tom Swinkels

04/03/2012 22:25:41
Quote Anchor link
Ok, maar een menuItem klasse spreekt mij niet zo aan. Een menuList klasse wel.
Wat zou je verder met een menu klasse van kunnen doen?

Verder weet ik ook nog niet goed hoe ik dit in OO moet oplossen met de sub items. Misschien dat het helpt om de manier te delen hoe ik het zonder OO deed. Misschien dat jullie dan weten hoe ik het in OO op de beste manier kan doen.

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
<?php
    public function getMenu($i_parentid)
    {

            $string = null;
            $result = $this->_db->prepare("SELECT
                                                    webn_name,
                                                    webn_url,
                                                    webn_parentid,
                                                    webn_id
                                            FROM
                                                    web_navigation
                                            WHERE
                                                    webn_state = 1
                                            AND
                                                    webn_parentid = ?
                                            ORDER BY
                                                    webn_order
                                            ASC
                                            "
);
            $result->execute(array($i_parentid));
            $list = $result->fetchAll();

            foreach($list as $array)
            {

                $string[] = $array;
            }

            return $string;
    }

                $getMenu = $index->getMenu(0);
                if(count($getMenu) > 0)
                {

                    foreach($getMenu as $menu)
                    {

                        echo '<li class="menu"' . ($menu['webn_url'] == $config->getUrl(1) ? ' class="select"' : '') . '>';
                        echo ($menu['webn_url'] != '' ? '<a href="' . SITE_PATH . $menu['webn_url'] . '/">' : '');
                        echo $config->replaceMessage($menu['webn_name']);
                        echo ($menu['webn_url'] != '' ? '</a>' : '');
                        
                        $getSubMenu = $index->getMenu($menu['webn_id']);
                        if(count($getSubMenu) > 0)
                        {

                            echo '<ul class="menusub">';
                            foreach($getSubMenu as $sub)
                            {

                                echo '<li class="menusub"' . ($sub['webn_url'] == $config->getUrl(1) ? ' class="select"' : '') . '>';
                                echo ($sub['webn_url'] != '' ? '<a href="' . SITE_PATH . $sub['webn_url'] . '/">' : '');
                                echo $config->replaceMessage($sub['webn_name']);
                                echo ($sub['webn_url'] != '' ? '</a>' : '');
                                echo '</li>';
                            }

                            echo '</ul>';
                        }

                        echo '</li>';
                    }
                }

                else
                {
                    echo 'ERROR: No menu items';
                }

                ?>


Toevoeging op 05/03/2012 17:54:51:

Als ik het zo zelf nog eens bekijk denk ik nu aan de volgende klasse:

-MenuListMapper
-getMenu($parentId)

-MenuList
-setName($name)
-setUrl($url)
-setParentId($parentId)
-setId($id)
-getName()
-getUrl
-getParentId()
-getId()

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
$menuListMapper = new MenuListMapper($db);
$menuList = $menuListMapper->getMenu(0);

$menuListSub = $menuListMapper->getMenu('PARENT_ID');


Of zou ik twee methode's moeten maken? Menu() MenuSub()?
Tocht ben ik er nog niet helemaal over uit. Hoop dat jullie mij beter kunnen helpen!
 
Mark Kazemier

Mark Kazemier

07/03/2012 12:27:44
Quote Anchor link
Ik zou persoonlijk net zoals Wouter J al zegt werken met een Menu en een MenuItem klasse. Een MenuItem is namelijk echt iets heel anders en deze zal ook eigen functionaliteit krijgen.

Het ophalen van het menu zou ik doen met een MenuRepository waar je gewoon direct het hele menu of het menu vanaf een bepaald subitem op kan vragen. Het liefst heb je niet dat de Menu en MenuItem klassen weten dat ze opgeslagen kunnen worden en hoe dit gebeurt. Dat maakt het later ook eenvoudiger om een XML opslag techniek te gebruiken bv.

Quote:
Maar omdat in OO alles draait om flexibiliteit zitten er ook nog aparte setters in, zodat je halverwege het script de url/name kunt wijzigen.


Zeer slecht argument. Een setter wel of niet definiëren heeft niets met flexibiliteit te maken. Sterker nog ik zou een setter alleen definiëren als ik hier een heel goede reden voor had. Het druist namelijk in tegen het OOP principe van het afschermen van data. Je doet dat op zo'n moment namelijk nog maar gedeeltelijk.

De meeste transities van state van een object zal je binnen het eigen object willen laten plaatsvinden. In een eigen methode. Op het moment dat je een setter maakt, geef je deze "macht" af aan andere klassen. Iedereen kan opeens deze state veranderen. Natuurlijk kan de setter wel logica bevatten, maar dit doet deze eigenlijk nooit.
 
Kees Schepers

kees Schepers

07/03/2012 12:49:31
Quote Anchor link
Het is een heeeeel oud script van me maar misschien heb je er wat aan:

http://www.phphulp.nl/php/script/php-algemeen/menu-ulli-structuur/1149/
 
Kris Peeters

Kris Peeters

07/03/2012 14:27:24
Quote Anchor link
Je hebt nog niets geschreven; je hebt een voorstel en vraagt of je nog "goe bezig" bent, of dit de richting is waarin je tijd en moeite wil investeren; juist?

Indien je bereid bent wat extra moeite te doen, kan je de structuur ook anders regelen.
MySQL heeft een systeem waarmee je gegevens kan ordenen, in een hiërarchische structuur.

Je kan dan oneindig complex (nu ja, ...) items in een hiërarchie steken, zonder op voorhand te moeten weten hoe diep de structuur moet gaan.

In jouw geval kan je dus een submenu hebben die zelf een aantal items hebben die submenu's hebben.
Tja, zoals dat dus het geval is bij menu's van programma's op je pc.

Hier vind je uitleg:
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Dus nog eens duidelijk maken: hiervoor zal je wat tijd moeten maken om het onder de knie te krijgen en waarschijnlijk is het overkill voor wat je nu nodig hebt.
Indien je het de moeite niet vind, ben ik de eerste om dit goed te begrijpen, doe dan maar voort zoals je bezig bent.
 
Tom Swinkels

Tom Swinkels

07/03/2012 14:45:11
Quote Anchor link
@Mark: Ik kan het menu (database) toch ook opvragen in de userMapper() klasse? Die heb ik later ook nodig voor het wijzigen?

@Kees: Bedankt, maar op die manier genereer je de HTML en niet de menu items zelf.

@Kris: Is het verstandig om dat met MySQL te doen? Ik ben dat ook nog nooit eerder tegen gekomen dus vraag mezelf af of het wel verstandig is om dat toe te passen.

--

Verder heb ik nog niet veel duidelijkheid over hoe ik de opbouw zou kunnen doen in OO. Hoe weet ik straks welk sub-item bij welk item hoort? Is het idee van de getters en setters wel goed?
 
Mark Kazemier

Mark Kazemier

07/03/2012 14:51:20
Quote Anchor link
Uhm, volgens mij begrijp je het helemaal verkeerd Tom.
Allereerst, wat heeft een menu met de user te maken? Dus waarom zou je dat opeens uit een UserMapper halen?

Dan de structuur die wij voorstellen zijn twee klassen:
- Menu
- MenuItem

Een menu is het hele menu. Het MenuItem is een los item uit het menu.
Voorbeeldje:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
Hoofdmenu
- Home
- Inloggen
- Forum
- Blog


Het hoofdmenu is nu een Menu, dus Menu object. De items Home, Inloggen, Form en Blog zijn nu MenuItems.
 
Tom Swinkels

Tom Swinkels

07/03/2012 15:00:11
Quote Anchor link
@Mark: Ik bedoelde MenuMapper() i.v.m UserMapper().
De klasse Menu en MenuItem hoeven niet te weten dat een menu uit de database komt daar zorgt de MenuMapper() voor.

Verder maakt de MenuMapper() het Menu() en MenuItem() object aan wanneer het menu uit de database word gehaald?

Begrijp ik het nu een beetje?
 
Kris Peeters

Kris Peeters

07/03/2012 15:09:16
Quote Anchor link
Mijn punt gaat om de manier waarom je je gegevens op zijn plaats zet in de hiërarchie.

Jij gaat uit van 1 top-menu, elk top-menu kan 1 generatie submenu's bevatten.
In dit geval kan je doen wat jij doet: het volstaat dat een submenu zijn parent (id) bijhoudt.

Trouwens, al eens nagedacht over de volgorde van de items van een submenu? Stel dat je (sub)item 5 eigenlijk liever op de tweede plaats hebt; hoe maak je dat duidelijk in de database?


Het systeem dat ik voorstel werkt niet met een parent-veld. Elk item heeft een left-waarde en een right-waarde (steeds een integer).
Elke left-waarde of right-waarde komt slechts 1 keer voor.
Met die waarden heeft elk item ondubbelzinnig zijn plaats in de structuur.

Dat laat gelijk welke boomstructuur toe. Zie vooral:
Afbeelding

Waar dit artikel over gaat, is dus een reeks sql statements die heel dit systeem regelen.
bv. indien right - left = 1 => dan weet je dat het een "leaf node" is: een blad, een eindpunt (geen subitems).
Je hebt statemants om - een hele tak te verhuizen naar een andere node, items van plaats te wisselen, ...

Het zit goed in mekaar; het werkt; het laat jou veel mogelijkheden toe.
... maar dan wel meer dan je vraagt; je moet zelf bepalen of het de moeite waard is.
Gewijzigd op 07/03/2012 15:11:11 door Kris Peeters
 
Tom Swinkels

Tom Swinkels

07/03/2012 15:22:17
Quote Anchor link
@Kris: Daar wilde ik een sort column voor maken.
Ik vind het idee van je wel erg interessant, enkel snap ik het nog niet helemaal "indien right - left = 1" geen sub-items.
Wanneer heeft het dan wel sub-items?
En hoe weet ik nu dat TELEVISIONS bijvoorbeeld een sub-item is?
 
Kris Peeters

Kris Peeters

07/03/2012 15:38:38
Quote Anchor link
Kijk eens naar "Portable electronics" (image).
Left: 10; right: 19.

Er zijn 8 getallen tussen 10 en 19, dus je weet dat er in totaal 4 nodes staan onder "Portable electronics".

Stel dat je de hele tak onder "Portable electronics" wil verwijderen. Dan moet je dus alles verwijderen met een left en right tussen de waarden 10 en 19.
Daarna moet het gat terug gevuld worden: alle getallen groter dan 10 moeten met 8 verminderen.

"Portable electronics" wordt dan: left: 10; right: 11.
Electronics wordt dan: left: 1; right 12

Zo is er dus een procedure voor alle mogelijke dingen die je met een boomstructuur kan uitsteken. En je moet die zelf niet uitvinden: die staan in het artikel
Gewijzigd op 07/03/2012 15:39:32 door Kris Peeters
 
Tom Swinkels

Tom Swinkels

07/03/2012 16:25:04
Quote Anchor link
@Kris: Het word nu een stuk duidelijker.
Enkel ben ik het nog niet helemaal eens over de manier, wanneer je een nieuw sub-item krijgt moeten alle nummertjes aangepast worden?
Gebruik je deze manier zelf ook voor een menu op te halen?
 
Kris Peeters

Kris Peeters

07/03/2012 17:11:27
Quote Anchor link
Elke verandering van de structuur zorgt er inderdaad voor dat meerdere records worden aangepast; enkel de velden lft en rgt (left en right zijn gereserveerde woorden), wel te verstaan.

Dit lijkt een vreemde manier van doen, maar het werkt.

Google eens "hierarchical mysql". Alle zoekresultaten vertellen het zelfde verhaal.
Dit artikel stond nog op de site van mysql zelf.
(Ik bedoel maar ... don't take my word for it, zie eens wat de rest van de wereld er van vindt; ik heb dit niet bedacht.)

De echte vraag is: is het de moeite waard voor wat je maar nodig hebt?

Dit soort dingen kan je vaak best eerst apart testen. Los van waar je echt mee bezig bent.

Het is al een aantal jaar geleden dat ik dit echt nog gebruikte. Toen was de noodzaak ook groter; de structuur was complexer dan de vraag die jij stelt.
 
Tom Swinkels

Tom Swinkels

07/03/2012 17:39:13
Quote Anchor link
@Kris: Ik zal eens google, het moet natuurlijk wel makkelijk uit te breiden zijn naar sub-item/sub-item bijvoorbeeld. Op jou manier is dat weer een stuk makkelijker. Stel er komt een klant naar mij en zegt ik wil onder sub-menu01 nog een menu hebben.

Toevoeging op 07/03/2012 17:54:08:

Ik heb een mooi artikel gevonden op Pfz.nl -> http://www.pfz.nl/wiki/hierarchie-in-een-database/ ik ga daar eens even naar kijken!

Toevoeging op 07/03/2012 19:02:40:

Ik heb volgende artikel: http://netters.nl/artikelen/php-en-mysql/hierarchie-in-de-database/ lees ik dat "Het modified preorder tree traversel model" de beste oplossing is, omdat dit de snelste manier is.
Echter kan je ook gewoon een view maken, en hoef hij die view alleen aan te passen wanneer er iets gewijzigd word.
Toch vind ik die andere manier wel makkelijk, alleen kost het extra rekentijd bij het aanmaken en verwijderen van een item.

Toevoeging op 07/03/2012 21:04:56:

Ik ben het nu voor elkaar echter gaat er nog iets mis, de resultaten kloppen niet er worden bepaalde dingen niet afgesloten?
Ook klopt het resultaat niet aangezien cat01, cat02 en cat03 hoofd items zijn.

Code:
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
$resultUser = $db->prepare("SELECT node.name, COUNT(*) - 1 AS lvl
FROM menu AS node,
        menu AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.lft, node.name
ORDER BY node.lft");
$resultUser->execute(array());
$listUser = $resultUser->fetchAll();

if(count($listUser) > 0)
{
    echo '<ul>';
    foreach($listUser as $i => $user)
    {
        echo '<li>
            '. $user['name'];
        if($listUser[$i+1]['lvl'] > $listUser[$i]['lvl'])
        {
            echo '<ul>';
        }
        elseif($listUser[$i+1]['lvl'] < $listUser[$i]['lvl'])
        {
            echo '</li>
                </ul>
            </li>';
        }
        else
        {
            echo '</li>';
        }
    }
    echo '</ul>';
}


Output:
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
<ul>
    <li>cat01
        <ul>
            <li>cat01A
                <ul>
                    <li>cat01B
                        <ul>
                            <li>cat01C1</li>
                            <li>cat01C2</li>

                                </ul>

                            </li>
                    <li>cat02</li>
                    <li>cat03
                        <ul>
                            <li>cat03A</li>

                                   </ul>

                            </li>
                </ul>


SQL

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
CREATE TABLE IF NOT EXISTS `menu` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(20) NOT NULL,
  `lft` int(11) NOT NULL,
  `rgt` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

--
-- Gegevens worden uitgevoerd voor tabel `menu`
--

INSERT INTO `menu` (`id`, `name`, `lft`, `rgt`) VALUES
(1, 'cat01', 1, 10),
(2, 'cat01A', 2, 9),
(3, 'cat01B', 3, 8),
(4, 'cat01C1', 4, 5),
(5, 'cat01C2', 6, 7),
(6, 'cat02', 11, 12),
(7, 'cat03', 13, 16),
(8, 'cat03A', 14, 15);
Gewijzigd op 08/03/2012 02:04:30 door Tom Swinkels
 
Kris Peeters

Kris Peeters

08/03/2012 11:35:33
Quote Anchor link
Ik heb vroeger ondervonden dat het een goed idee is om altijd een root te hebben waar iedereen van afstamt.
Eventueel een dummy node (noem die bv. root).

Een aantal bewerkingen worden veel lastiger als je geen root hebt (bv. een tak verplaatsen onder een andere node)

Zie dat je zeker een veld depth in je records hebt (jij noemt die lvl, als ik het goed heb).
depth = 0 => (dummy) root
depth = 1 => menu
depth = 2 => submenu

Je werkt met pdo?
Dat is al interessant. Het zal nodig zijn tables te locken en pas te commiten op commando.

Er kunnen best een aantal functies gemaakt worden om de boel wat meer overzichtelijk te maken. Het zijn lange queries.

iets als
insert_as_child($db_object, $parent_id) // inserten onder een node, als eerste subitem (eventueel al de rest opschuiven naar rechts)

insert_as_sibling($db_object, $sibling_id) // inserten als broer/zus rechts van een node

Dat wordt wel een interesante oefening om dit goed te structureren.

Dat openen en sluiten van ul's en li's ... dat is wat zoeken. Nu onmiddelijk even geen tijd, sorry

Tom Swinkels op 07/03/2012 17:39:13:
Toch vind ik die andere manier wel makkelijk, alleen kost het extra rekentijd bij het aanmaken en verwijderen van een item.


Dat is juist.
Maar je moet dat wel zien vanuit de verhouding van het aantal keer dat je de data schrijft/update ten opzichte van hoe veel je data leest.

Je zal ook liever een thumbnail maken op het moment van de upload; dan telkens de GD library aan te spreken bij het bekijken van de foto galerij
Gewijzigd op 08/03/2012 11:36:34 door Kris Peeters
 
Tom Swinkels

Tom Swinkels

08/03/2012 13:43:28
Quote Anchor link
Ik ben er nu achter dat het script wat ik gebruik niet complex genoeg is.
En hij alleen tot een x aantal sub-menu's goed werkt.
Nu heb ik even een schema gemaakt waar ik even vanuit ga: Afbeelding

Als de left en right van de menu items tussen de 1 en 12 hoort het allemaal onder menu 01.
Wanneer de left en right van de menu items tussen de 2 en 9 zitten horen de items onder het sub-menu 01-1A.
Ik weet echter niet hoe ik dit goed kan uitrekenen, hopelijk kan iemand mij hierbij helpen.
 
Mark Kazemier

Mark Kazemier

09/03/2012 14:03:08
Quote Anchor link
Het principe dat hierboven wordt beschreven is het Nested Set model. Een zeer bekend model om hiërarchische structuren op te slaan in een database.

De techniek werkt erg leuk voor als je de volledige boom of een deel daarvan in één keer wil opvragen. Dat kan namelijk eenvoudig met een enkele query die gebruik maakt van de left en de right waarden. Er zijn alleen ook een paar nadelen:
- Het is heel lastig om inserts te doen. Je zal dan heel de boom opnieuw moeten uitrekenen en alle left en right waarden aan moeten passen. Je kan dit wel afvangen door grotere marges te nemen, maar vroeg of laat krijg je hier toch een probleem mee
- Je hebt geen mogelijkheid om de consistentie van je structuur af te dwingen doormiddel van constraints. Hierdoor kunnen er eenvoudig fouten ontstaan doordat je left en right waarden tussen twee menu items overlappen
- Het ophalen van een enkel niveau in je boom is erg lastig

Een andere manier om het op te slaan die in principe ook veel logischer is door een link te maken van een menu_item naar een ander menu_item waar deze onder moet vallen. Je geeft je menu item dus een parent_id. Dit parent_id is null als er geen parent is.

Deze techniek heeft een aantal voordelen:
- Het is eenvoudiger om nieuwe menu_items toe te voegen. Dit kan gewoon door een nieuw record toe te voegen. Je hoeft de andere records niet aan te passen
- Je kan eenvoudig een enkele laag uit je boomstructuur opvragen
- Je kan de consistentie van je boom afdwingen doormiddel van foreign keys

Natuurlijk heeft deze techniek ook nadelen:
- Je hebt recursie nodig om alle records uit een boom op te vragen. Dit kan je in PHP doen door voor elke laag in de boom een query uit te voeren of doormiddel van common table expressions.

Overigens heeft de hele discussie over hoe je dit op gaat slaan in de database zeer weinig te maken met je object model in je applicatie. Dat is namelijk de grap van OOP en met name het Domain model pattern. Je domein model beschrijft de entiteiten en de business rules, maar weet niets af van persistence. Dat is iets dat je vervolgens in een architecture layer neerzet en laat beheren door een ORM of iets dergelijks.
 
Tom Swinkels

Tom Swinkels

11/03/2012 22:46:34
Quote Anchor link
Bedankt voor alle reacties.
Ik ben toch afgestapt van het Nested Set model, er zitten toch teveel nadelen aan.
Nu wil ik een recursive manier gebruiken, ik heb hier een stuk op internet gevonden en dat werkt. Nu wil ik die manier ombouwen tot OO in klasses.

De HTML wil ik niet in de klasse, het moet wel makkelijk zijn om hem bijvoorbeeld om te bouwen naar een template.

Ik zou dit splitsen tot 3 klasses (Menu, MenuItem en MenuMapper). Enkel kan ik de opbouw nog niet helemaal thuis brengen.
Misschien dat jullie mij nog wat tip's kunnen geven?

Mijn opbouw tot nu toe
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
<?php
class Menu
{
    function
getMenu()
    {

    }
}

class MenuItem
{
    private $_data;
    private $_list;
    private $_id;
    private $_parentId;
    
    public function __construct()
    {

        $this->_data = array();
    }

    public function setList($list)
    {

        $this->_list = $list;
    }

    public function setId($id)
    {

        $this->_id = $id;
    }

    public function setParentId($parentId)
    {

        $this->_parentId = $parentId;
    }

    public function getIds()
    {

        return $this->_data['ids'][$this->_id] = $this->_list;
    }

    public function getParents()
    {

        return $this->_data['parents'][$this->_parentId][] = $this->_id;
    }
}

class MenuMapper
{
    public function __construct(PDO $db)
    {

        $this->_db = $db;
    }

    public function getMenu()
    {

        $resultWebn = $this->_db->prepare("SELECT
                                                 webn_id,
                                                 webn_parentid,
                                                 webn_name
                                           FROM
                                                 web_navigation
                                           ORDER BY
                                                 webn_parentid, webn_name
                                          "
);

        $resultWebn->execute(array());
        $listWebn = $resultWebn->fetchAll();

        foreach($listWebn as $list)
        {

            $menuItem = new MenuItem();
            $menuItem->setList($list);
            $menuItem->setId($list['webn_id']);
            $menuItem->setParentId($list['webn_parentid']);
            return $menuItem;
        }
    }
}

?>


Download
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
<?php
$result
= $db->prepare("SELECT
                            webn_id, webn_parentid, webn_name
                        FROM
                            web_navigation
                        ORDER BY
                            webn_parentid, webn_name
                      "
);

$result->execute(array());
$listWebn = $result->fetchAll();

$menuData = array(
    'items' => array(),
    'parents' => array()
);


foreach($listWebn as $list)
{

    $menuData['items'][$list['webn_id']] = $list;
    $menuData['parents'][$list['webn_parentid']][] = $list['webn_id'];
}

function
buildMenu($parentId, $menuData)
{

    $html = null;
    if (isset($menuData['parents'][$parentId]))
    {

        $html = '<ul>';
        foreach ($menuData['parents'][$parentId] as $itemId)
        {

            $html .= '<li><a href="">' . $menuData['items'][$itemId]['webn_name'] . '</a>';

            $html .= buildMenu($itemId, $menuData);

            $html .= '</li>';
        }

        $html .= '</ul>';
    }

    return $html;
}

?>
Gewijzigd op 11/03/2012 23:08:12 door Tom Swinkels
 



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.