Menu klasse

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Traineeship Full Stack .NET Developer

Dit ga je doen Start op 7 augustus 2023 bij de Experis Academy en ontwikkel jezelf tot een gewilde Full Stack .NET Developer. Maar hoe ziet het traineeship eruit en wat kun je verwachten? Periode 1 De eerste 3 maanden volg je fulltime, vanuit huis, een op maat gemaakte training in teamverband. Je leert belangrijke theorie en krijgt kennis van de benodigde vaardigheden en competenties die nodig zijn om de IT-arbeidsmarkt te betreden. Zowel zelfstandig als in teamverband voer je praktijkopdrachten op het gebied van front- en backend development uit. Wat er per week op het programma staat kun je

Bekijk vacature »

C#.NET-developer - JUNIOR

Functie omschrijving Voor een leuke opdrachtgever in omgeving Brielle zijn wij op zoek naar een junior developer. Werk jij graag met de volgende tools & technieken? C#, .NET, ASP.NET, MVC en SQL? Kijk dan snel of dit iets voor jou is! Als programmeur bij een productiebedrijf zal je voornamelijk nieuwe software schrijven maar ook bestaande software verbeteren. Verder werk je veel samen in back end projecten met leuke collega's. Bedrijfsprofiel Met een team van ruim 130 personen staan ze elke dag weer klaar om IT en Business te combineren door het ontwikkelen van producten op maat. Er zijn 3 teams,

Bekijk vacature »

Medior PHP Developer

Functie omschrijving Ben jij een getalenteerde PHP Developer en aan de slag in een gemotiveerd team? Lees dan snel verder! Voor onze opdrachtgever in de omgeving van Valkenswaard zijn we op zoek naar een ervaren PHP developer. Jij gaat hier zorg dragen voor het optimaliseren en up-to-date houden van de bestaande applicaties. Je werkt verder aan de applicaties die jij verder ontwikkelt. Dit doe je voornamelijk met PHP en MySQL. Verder ga je je bezig houden met: Het uitbouwen van het E-commerce software platform. Deelnemen aan overleggen met het team. Het ondersteunen van jouw team developers (3 man) en helpen

Bekijk vacature »

Java developer Zorgsysteem

Dit ga je doen Werken aan het eigen gebouwde zorgsysteem; Verbeteringen maken en toepassen binnen de applicatie; Jij gaat werken aan de Back-end van de applicatie en sporadisch werk je mee aan de Front-end; Samenwerken met andere teams voor een optimaal resultaat; Jij kan 'clean' werken en high quality code schrijven; Jij werkt resultaatgericht. Hier ga je werken De organisatie houdt zich bezig met diverse applicaties met betrekking tot zorgregistratie. Dankzij hun systeem komt alle informatie, omtrent de zorg van een patiënt, op een overzichtelijke en toegankelijke manier samen in één systeem te staan. Op deze manier is deze informatie

Bekijk vacature »

Front-end developer Consultancy in teamverband wer

Functie Het team bestaat uit User Experience designers, Data Scientists en Software Engineers. Momenteel zijn ze op zoek naar een ervaren Front-end of Fullstack developer die samen met de consultants aan de slag gaat om de business requirements te vertalen naar technische oplossingen. Los van het finetunen van extenties, help je bij het configureren van bijvoorbeeld een mobiel bankieren app. Hierin ben je van A tot Z betrokken en zie je bijvoorbeeld ook toe op de uitvoering van testen. Je expertise wordt optimaal benut en je krijgt verschillende kansen om deze uit te breiden door met verschillende innovatieve technologieën aan

Bekijk vacature »

Fullstack developer

Functie omschrijving We are looking for a dutch native speaker Wil jij werken als Senior Developer en werken aan een applicatie die duizenden marketingcampagnes automatisch aanstuurt? Dit is je kans! Kom werken voor onze opdrachtgever en in deze rol zul je veel vrijheid en verantwoordelijkheid krijgen om gezamenlijk de applicatie naar een hoger plan te tillen. Wat ga je verder doen: Optimaliseren, beheren en uitbreiden van onze applicatie; Het bouwen van aansluitingen op de systemen van partners middels API’s; Meedenken over de technische/ontwikkel-standaarden; Proactief verbeterpunten voorstellen. Bedrijfsprofiel Het is een organisatie die met een team van verschillende developers én marketeers

Bekijk vacature »

C#.NET Developer

Dit ga je doen Ontwikkelen van de Back-end in .NET6 / C# en WebAPI (Focus);) Ontwikkelen van de Front-End in Nodje.js en Angular (secundair); Opstellen van een technisch ontwerp; Testen, documenteren en implementeren van de nieuwe applicatie; Verzorgen van de nazorg, na de implementatie; Het oplossen van bugs en incidenten. Hier ga je werken Als C#.NET Developer binnen deze organisatie kan jij het verschil maken. Zij werken momenteel nog met programmatuur die is ontwikkeld in C++. Hiervan gaan zij afscheid nemen zodra alle nieuwe software in C#.NET geschreven is. Een grootschalig en langdurig project. Voor hen is deze software van

Bekijk vacature »

Medior Java developer (fullstack)

Wat je gaat doen: Of beter nog, wat wil jij doen? Binnen DPA GEOS zijn we dan ook op zoek naar enthousiaste Java developers om ons development team te versterken. Als Java developer werk je in Agile/Scrum teams bij onze klanten en daarbij kun je eventueel ook andere ontwikkelaars begeleiden in het softwareontwikkelproces. Verder draag je positief bij aan de teamgeest binnen een projectteam en je kijkt verder dan je eigen rol. Je gaat software maken voor verschillende opdrachtgevers in jouw regio. Je bent een professional die het IT-vak serieus neemt en kwaliteit levert. Je leert snel vanwege je diepgaande

Bekijk vacature »

Low Code Developer - Consultant

Functie omschrijving Wil jij fungeren als een spin in het web en samenwerken met klanten? Voor een leuke en interessante opdrachtgever in omgeving Leiden zijn wij op zoek naar een Low Code developer die zich bezig gaat houden met het optimaliseren van bedrijfsprocessen bij klanten en het leiden van projecten. Ben jij toe aan een nieuwe uitdaging en heb jij verstand van datamodellering en NO CODE Platformen? Lees dan snel verder! Bij deze rol horen de volgende werkzaamheden: Je gaat geen code kloppen maar bedenken hoe applicaties eruit moet komen te zien. Je gaat werken met een non code platform,

Bekijk vacature »

Developer Angular & Kotlin

Dit ga je doen Het (door)ontwikkelen van mobiele apps en webapplicaties; Het opstellen van technisch ontwerp en het bespreken van ontwerpen met de software architect; Het uitvoeren van werkzaamheden op het gebied van technisch testen; Het in de gaten houden van nieuwe ontwikkelingen op jouw vakgebied en het adviseren van de organisatie hierover. Hier ga je werken Het gaat om een bekend internationaal handelsbedrijf met ruim 800 medewerkers, verdeeld over verschillende deelbedrijven. Deze organisatie is van oorsprong een familiebedrijf, er wordt hard gewerkt, er heerst een no nonsense en doeners mentaliteit, een informele sfeer en er is een mix van

Bekijk vacature »

Java developer

Als Java Developer bij Sogeti ben je onderdeel van onze toonaangevende community die bestaat uit ruim 100 gepassioneerde Java professionals. In teamverband lever je mooie prestaties. Daarmee draag je aan bij de meerwaarde die wij leveren aan onze top-opdrachtgevers. Geen werkdag is hetzelfde! Je bent voortdurend bezig met het oplossen van allerlei complexe vraagstukken binnen bedrijfs kritische systemen voor onze klanten in regio Noordoost zoals DUO, ING, CJIB en Tendernet. Natuurlijk krijg jij de mogelijkheid je verder te certificeren in dit vakgebied. We organiseren regelmatig technische Meetups en doen veel aan kennisdeling. Sogetisten hebben plezier in hun werk en staan

Bekijk vacature »

Airport Developer / System engineer

De functie Als onze nieuwe Airport Developer / System Engineer is je doel om uit nieuwbouw- en onderhoudsprojecten maximale waarde te creëren voor Schiphol Group en haar stakeholders. Vanuit je visie en expertise, maar ook (technologische) ontwikkelingen, wetgeving en beleid vertaal je klantwensen naar een gedegen programma van eisen. In de planontwikkelingsfase werk je nauw samen met Plan Ontwikkelaars om je kennis in te brengen ten behoeve van de kwaliteit van het investeringsvoorstel. Je overlegt met diverse partijen, stelt de vraag achter de vraag en verbindt zo de belangen van de luchthaven, proceseigenaar en asseteigenaar om tot een gedragen ontwikkelopgave

Bekijk vacature »

Ervaren C#.NET programmeur

Functieomschrijving Voor een moderne werkgever in regio Prinsenbeek zijn wij op zoek naar een ervaren C#.NET programmeur die graag de uitdaging aangaat. Je houdt je bezig met het ontwikkelen van maatwerk webapplicaties voor diverse klanten, waarbij complexe processen optimaal worden ondersteund. Verder ziet jouw takenpakket er als volgt uit: Ontwikkelen en onderhouden van C#.NET-applicaties; Schrijven van hoogwaardige, herbruikbare codes; Schrijven van technische documentatie en gebruikershandleidingen; Bijdragen aan het ontwerp en de architectuur van softwaretoepassingen; Troubleshooten en oplossen van bugs in softwaretoepassingen; Werken met databases en dataopslagoplossingen; Implementeren van beveiligingsoplossingen en het waarborgen van de beveiliging van applicaties en gegevens. Bedrijfsprofiel

Bekijk vacature »

Back-end programmeur

Functieomschrijving Heb jij recent jouw HBO ICT diploma in ontvangst mogen nemen? Of ben je toe aan een nieuwe uitdaging? Voor een erkende werkgever in regio Waalwijk zijn wij op zoek naar een back-end developer. Kennis of ervaring met C# & SQL is een must! Je houdt je bezig met het ontwikkelen van nieuwe functionaliteiten; Je bent verantwoordelijk voor de beheer en ontwikkeling van de software; Je draagt bij aan de implementatie van aanpassingen, verbeteringen en aanvullingen in de C# based applicaties; Je test de software en ontwikkelt deze door; Je brengt de aanpassingssuggesties van klanten in kaart, om ze

Bekijk vacature »

Senior Organisatieontwikkelaar

Als Organisatieontwikkelaar zorg je ervoor dat we in het magazijn van Coolblue altijd vooruit voetballen op het gebied Medewerker en Organisatie Ontwikkeling. Zo draag je bij aan een toekomstbestendig magazijn waar we klanten én medewerkers elke dag blijven verwonderen. Wat doe je als Senior Organisatieontwikkelaar bij Coolblue? Als Organisatieontwikkelaar werk je voor het magazijn van Coolblue. Je krijgt er energie van om continue te bouwen aan een toekomstbestendige organisatie. Dat doe je samen met 17 collega's in het HR-team, ieder met een eigen specialisme. Je werkt graag zelfstandig en je weet snel je weg te vinden als verandermanager. Ook ben

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

05/11/2024 15:33:50
 
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.