Menu klasse

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Junior .NET developer

Functie Om half 9 kom jij binnen en pak jij als eerst natuurlijk een bakje koffie of thee. Vervolgens ga jij je voorbereiden op de stand-up van kwart voor 9. Zijn er bijvoorbeeld dingen waar jij nog tegen aan loopt? Of is er nog code die getest of gereviewd moet worden? Vervolgens starten jullie met de stand up en na de stand up zoeken jullie elkaar op en gaan jullie aan de slag. Als team met 6 developers werken jullie in drie wekelijkse sprints. Het einde van een sprint is altijd op een donderdag zodat jullie op vrijdag de demo

Bekijk vacature »

Laravel PHP developer in een jong team

Bedrijfsomschrijving Als je op zoek bent naar een werkplek waar plezier en uitdaging hand in hand gaan, dan is dit bedrijf de juiste keuze voor jou. Hier kun je werken aan uitdagende projecten en krijg je als developer veel verantwoordelijkheid. Het bedrijf waardeert kwaliteit boven kwantiteit en richt zich op het ontwikkelen van hoogwaardige applicaties en websites waar klanten enthousiast over zijn. Dit bedrijf is vooruitstrevend en streeft naar het leveren van de best mogelijke resultaten voor hun klanten. Als medior PHP ontwikkelaar met 3 jaar ervaring ben jij de persoon die we zoeken. Je krijgt hier de kans om

Bekijk vacature »

.NET developer

Functie Als .NET ontwikkelaar start jij in een multidisciplinair team met 7 ontwikkelaars. Dit team is verdeeld onder Front-end ontwikkelaars en backend developers. De backend developers werken voornamelijk aan desktop applicaties in combinatie met backend systemen. Hier ga jij dus ook mee aan de slag! Hierbij wordt voornamelijk gebruik gemaakt van C# .NET, WPF, UWP, XAML en MVVM. WPF, UWP, .NET Core, Azure Devops en Entity Framework. WPF en UWP worden dan ook voornamelijk gebruikt voor de user interface van de desktop applicatie. Het development team is dan ook erg gedreven m.b.t. het ontwikkelen van vooruitstrevende en innovatieve horeca automatiseringsoplossingen.

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 »

Senior PHP Developer

As a Senior PHP Developer at Coolblue, you ensure that our webshops work as optimal as possible and you choach other colleagues on the hard and soft skills. How do I become a Senior 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

Bekijk vacature »

Software Programmeur PHP

Functie Wij zijn op zoek naar een PHP programmeur voor een leuke opdrachtgever in omgeving Alblasserdam. Heb jij altijd al willen werken bij een bedrijf dat veilige netwerkverbindingen levert door middel van veilige oplossingen? Lees dan snel verder. Hoe kan jouw dag er straks uitzien? Je gaat software en webapplicaties ontwikkelen met behulp van de talen C / C++ / PHP. Je gaat technische klussen uitvoeren op locatie bij klanten. Je onderhoudt contact met de projectleider om er zeker van te zijn dat een projecten goed verlopen. Je gaat klanten ondersteunen op het gebied van geleverde software en webapplicaties. Tevens

Bekijk vacature »

C# .NET developer voor innovatieve applicaties gez

Bedrijfsomschrijving Deze werkgever houdt zich al ruim 20 jaar bezig met het ontwikkelen van innovatieve software en dat willen ze graag nog lang doorzetten. En dat merk je ook als je als .NET developer hier aan de slag gaat. De applicaties worden continu doorontwikkeld met altijd als uitgangspunt dat zowel de kwaliteit als het gebruikersgemak van hoog niveau is. Het bedrijf telt inmiddels ruim 25 medewerkers waarvan meer dan de helft op de development afdeling werken. Meer weten over deze werkgever? Mail naar [email protected] of bel 0657578548 Functieomschrijving Je komt te werken in een Scrum team met andere .NET developers

Bekijk vacature »

PHP Developer

Functie Middels Scrum en sprints bouw jij in deze functie mee aan complexe webapplicaties en ons SaaS platform. Hierbij hoort ook architectuur tot een van je taken. Daarnaast ben je één van de leden van het Scrum team. Dat betekent dat je naast je kerntaken ook in contact staat met de product owner. Oftewel, je bent bij het gehele ontwikkelproces betrokken. Tools die hierbij gebruikt worden zijn o.a. PHP, Symfony en Git. Eisen • Minimaal HBO werk- en denkniveau • Minimaal 3 jaar aantoonbare ervaring met PHP • Kennis en ervaring Symfony (Laravel is pré) & Lando • Kennis van

Bekijk vacature »

Java Developer

Dit ga je doen Als Java Developer ben je verantwoordelijk voor: Het ontwikkelen van nieuwe en bestaande webservices; Het uitbreiden van functionaliteiten binnen de producten- en dienstenportefeuille; Het werken aan gegevensuitwisseling met bijvoorbeeld SOAP; Testen van frameworks met gebruik van UNIT en Selenium. Hier ga je werken De organisatie waar je komt te werken is een semi-overheidsinstelling, gesitueerd in Utrecht en zorgt voor een goede samenwerking tussen verschillende overheidsinstanties. Het is een familiaire club die gaat voor kwaliteit en langdurige relaties. Zo zorgen zij ervoor dat er op grote schaal vertrouwelijke informatie tussen verschillende overheidsinstellingen wordt uitgewisseld. Hun werk zorgt

Bekijk vacature »

Softwareontwikkelaar Cleopatra

Functieomschrijving Voor de gemeente Amsterdam zijn wij op zoek naar een softwareontwikkelaar Cleopatra. De directie Verkeer en Openbare ruimte van de gemeente Amsterdam beschikt over een softwareapplicatie, "Cleopatra", waarmee geautomatiseerde handhaving plaatsvindt (op basis van kentekenherkenning) van bepaalde gebieden waarin toegangseisen worden gesteld aan het verkeer. Voorbeelden ervan zijn de milieuzones, de zone zwaar verkeer, handhaving van brom- en snorfietser op het fietspad en autoluwe gebieden. Voor de doorontwikkeling en uitbreiding ervan zijn gespecialiseerde softwareontwikkelaars nodig die helpen bij het programmeren van de handhavingsmodules voor nieuwe gebieden en het verbeteren en bijwerken van de bestaande onderdelen van de softwareapplicatie. Functie

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 »

Medior PHP developer

Functie Samen met je development team werk je Agile Scrum en met jullie gezamenlijke kennis en ervaring bepalen jullie samen de beste keuze voor techniek en architectuur. Naast het ontwikkelen van software ben je continue bezig om ook jezelf te ontwikkelen. Ze werken met o.a.: PHP, Laravel, Doctrine, PHP Unit, Behat, React, TypeScript, (My)SQL, Postgress, Redis, ElasticSearch, Docker, Nginx, GIT flow, JIRA, AWS. Eisen • HBO werk- en denkniveau • Je hebt goede kennis en ervaring met PHP • Je bent niet bang voor complexe projecten • Je werkt graag zelfstandig aan applicaties • Je bent altijd nieuwsgierig naar nieuwe

Bekijk vacature »

Front-end (Angular) developer - remote werken

Functie Als Front-end (Angular) developer ga je aan de slag met het uitbouwen van hun webapplicatie, als één van de front-end experts ga je samen met collega’s in een devops team werken aan een nieuw front-end voor hun calculatie oplossing. Binnen de calculatiesoftware kunnen meerdere professionals tegelijk samenwerken, 3D calculaties uitvoeren en ook inzien met de benodigde specifieke details. Deze software wordt veel ingezet om projectbeschrijvingen en kosten in kaart te brengen, en tijdens de uitvoering te bewaken. Maar hiernaast liggen er in de toekomst veel meer plannen op het gebied van front-end in de andere applicaties. Genoeg te doen

Bekijk vacature »

PHP Laravel Ontwikkelaar

Functie omschrijving Weet jij alles over Laravel en krijg je energie van het developen van software hiermee? Laat het weten want wij zoeken een PHP/Laravel developer in regio 's-Hertogenbosch voor klein bedrijf welke softwareoplossingen maakt voor hun klanten. Jouw taken hierbij: Softwareapplicaties ontwikkelen en verder optimaliseren in veel diverse projecten op basis van Agile/Scrum. Documentatie schrijven over applicaties. Uitleg geven over software en applicaties Klantcontact hebben over bestaande applicaties. Techstack: PHP, Laravel, HTML, CSS, Javascript. Bedrijfsprofiel Deze organisatie zit in de regio van 's-Hertogenbosch en is een klein bedrijf. Er werken circa 15 medewerkers, verdeeld in meerdere teams, zoals back-end

Bekijk vacature »

Back-end Developer C#

Functie omschrijving We are looking for a dutch native speaker Ben jij een ervaren back-end developer, die graag in een in-house functie wil werken? Passen de woorden innovatie, programmeren en teamspeler bij jou? Zoek niet verder en lees snel verder. Voor een echt familiebedrijf in de regio van Uden ben ik op zoek naar een back-end developer, die met name kennis heeft van C# en .NET. Jij gaat de interne applicaties verder optimaliseren en nieuwe features ontwikkelen. Verder ga je de volgende werkzaamheden uitvoeren: Ondersteunen gebruikers; Uitvoeren van analyses van de software/applicaties; Maken van functionele ontwerpen en deze door vertalen

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

27/05/2026 09:43:36
 
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.