1 Extra voorbeelden 1 Objectenhierarchie 2 Kalender2 PHP EN MYSQL de basis 1.1 Uitgebreid voorbeeld van een objectenhierarchie We zullen een aantal ke...
1.1 Uitgebreid voorbeeld van een objectenhierarchie We zullen een aantal kenmerken van objectgeoriënteerd programmeren toelich‐ ten met behulp van een voorbeeld. Het voorbeeld gaat over de taxonomie van het dierenrijk, u vast wel bekend, over zoogdieren en vissen en zo. U moet er niet te veel achter zoeken, want als u zou proberen te veel details aan ons voorbeeld toe te voegen, dan zult u merken dat de principes van de zuivere objectoriëntatie u in de steek zullen laten. Hierbij eerst een plaatje:
Afbeelding 1.1 Een objectenhierarchie.
1.1.1 De klasse Dier Zoals u aan het plaatje kunt zien, is Dier de klasse waarvan alle andere klassen worden afgeleid, dus daar beginnen we mee:
2
Extra voorbeelden
kleur; } public function kanLopen() { return 'Ik weet het niet'; } public function kanZwemmen() { return 'Ik weet het niet'; } public function kanVliegen() { return 'Ik weet het niet'; } } ?>
We stippen een aantal punten aan: De klasse Dier is gedefinieerd als abstract. Dit betekent dat u er niet echt een object van kunt aanmaken. We kunnen alleen objecten maken van klassen die een echte soort aanduiden, zoals Meeuw en Kabeljauw. Natuurlijk hebben dieren meer eigenschappen dan hier genoemd, in het kader van het voorbeeld vragen we ons alleen af of een dier kan vliegen, zwemmen, of lopen en of het dier misschien een kleur heeft. De property $kleur is als protected gedefinieerd, dus we moeten een public methode maken om de kleur te kunnen laten zien. Dit is de methode getKleur(). Stel dat we toch zouden proberen om een Dier‐object te maken: $moppie = new Dier();
We krijgen dan een foutmelding bij het uitvoeren van een script met deze code‐ regel erin:
Fatal error: Cannot instantiate abstract class Dier in C:\xampp\htdocs\debasis\hoofdstuk05\extra-voorbeeld-dieren\test1.php on line 5 3
PHP EN MYSQL de basis
1.1.2 De abstracte klassen Vis, Zoogdier en Vogel We kunnen nog een paar abstracte klassen definiëren, voor Zoogdier, Vis en Vogel: abstract class Vis extends Dier { public function kanZwemmen() { return 'Ja'; } } abstract class Zoogdier extends Dier { public function kanLopen() { return 'Ja'; } } abstract class Vogel extends Dier { public function kanVliegen() { return 'Ja'; } }
1.1.3 Concrete klassen Deze code zegt dat vissen kunnen zwemmen, zoogdieren kunnen lopen en vo‐ gels kunnen vliegen, maar verder weten we nog niet veel over deze diersoorten en we kunnen nog steeds geen objecten maken. We breiden ons script daarom uit met een echt dier: class Meeuw extends Vogel { public function __construct(){ $this -> kleur = 'wit'; } }
Let erop dat we eigenlijk niets over meeuwen zeggen, behalve dat ze wit van kleur zijn. Laten we eens kijken naar het gedrag en de eigenschappen van Karel, een meeuw, met de volgende code (hoofdstuk05/extra‐voorbeeld‐dieren/test2.php): '; $karel = new Meeuw(); echo 'Kan Karel, een ', get_class($karel), ', vliegen? '; echo $karel -> kanVliegen(); echo ' '; echo 'Kan Karel lopen? ';
Kan Karel, een Meeuw, vliegen? Ja Kan Karel lopen? Ik weet het niet Karels' kleur: wit Laten we bekijken waarom u dit resultaat krijgt. We beginnen met de definities van de dierenklassen toegankelijk te maken in ons testscript door require_once 'dieren.php'; aan het begin van ons script te zetten. De methode kanVliegen() staat niet in de klasse Meeuw, maar alle meeuw‐ objecten hebben ook alle Vogel‐eigenschappen en daar is kanVliegen() wel gedefinieerd en dat geeft het antwoord “Ja”. Voor het antwoord op de volgende vraag, kanLopen(), moeten we nog een stap hoger kijken, naar de methoden die in de klasse Dier staan vermeld, want voor vogels staat deze methode niet vermeld. Voor dieren in het algemeen weten we niet of ze kunnen lopen, dus het antwoord is nu “Ik weet het niet”. En dan de kleur. $kleur is een protected property in de klasse Dier. Dat be‐ tekent dat deze property beschikbaar is in subklassen van Dier, maar niet buiten Dier. We kunnen dus niet schrijven: $karel->kleur. Daarom hebben we een methode gemaakt getKleur(), die wel de property $kleur kan benaderen in Dier en die publiek toegankelijk is. Ten slotte de methode get_class(). Deze methode is onderdeel van een serie methodes waarmee informatie over objecten en klassen verkregen kan worden. De get_class() methode heeft als parameter een object en hij geeft de naam van de klasse waartoe het object behoort terug, of FALSE als het geen object is. We hebben in de klasse Vogel gezegd dat een vogel‐object kan vliegen. Dat is leuk voor meeuwen, roodborstjes en zelfs futen, maar hoe zit dat met pinguïns? Een pinguïn is wel een vogel, maar hij kan niet vliegen. We kunnen dit tot uitdrukking brengen door de klasse Pinguin als volgt te definiëren:
5
PHP EN MYSQL de basis
class Pinguin extends Vogel { public function kanZwemmen() { return 'Ja'; } public function kanVliegen() { return 'Nee'; } }
Nu kunnen we dingen over Happy Feet te weten komen: kanVliegen (); echo ' '; echo 'Kan Happy Feet lopen? ', $happyFeet -> kanLopen(); ?>
De antwoorden zijn:
Kan Happy Feet, de Pinguin vliegen? Nee Kan Happy Feet lopen? Ik weet het niet
OEFENING 1.1
BREID HET DIERENRIJK UIT
Breid het dierenrijk uit met een paar zoogdieren, zoals Beer, Walvis, Mens. En een paar vissen, zoals Zalm, Kabeljauw. Maak een methode: kanPraten(). Bedenk dat mensen en papegaaien kunnen praten, maak ook een klasse voor Papegaai. Maak een methode vindLekker(), die als parameter een voedingsmiddel accepteert. Maak een paar voorbeelden zoals: $pooh->vindLekker ('honing'); Maak een script om informatie over de klasse Meeuw te weten te komen, zoals: welke methoden zijn er, welke property’s en de klasse waar Meeuw van is afgeleid (de superklasse). Hint: begin met zoeken naar get_class in het PHP manual, u komt dan uit bij een sectie over Classes/Objects en van daaruit kunt u de methodes vinden die u nodig heeft.
6
Extra voorbeelden
2.1 Project: Kalender We hebben nu voldoende kennis om een interessant project aan te pakken. Wat gaan we doen? We maken een kalender die u ook kunt inzetten als agenda. De eerste versie zal alleen de huidige maand laten zien, of een maand naar keuze. Eventueel zou u er iedere maand een andere foto naast kunnen zetten, net als bij een kalender aan de muur. Later, in een volgend hoofdstuk, zullen we manieren bedenken om afspraakinfor‐ matie aan uw kalender toe te voegen en met een beetje extra CSS of JavaScript, en natuurlijk beveiliging, is het ook mogelijk uw agenda te raadplegen op uw smartphone. Als datumprikker is een PHP‐kalender minder geschikt. U kent ze vast wel: als u een vliegticket via het internet bestelt, dan ziet u vaak een keuzemenu waarmee u op een makkelijke manier de reisdata kunt kiezen. Voor dit doel zijn uit‐ stekende JavaScript‐componenten beschikbaar. Alleen als u een site moet bedie‐ nen waar JavaScript onmogelijk is, zou kunnen overwegen het met PHP te doen.
2.1.1 Kalenderontwerp De kalender biedt weinig interactie met de gebruiker. Alleen de knoppen voor volgende en vorige maand betekenen dat er een verandering van het getoonde moet optreden. De eerste versie van de kalender/agenda is statisch. We tonen de kalender in een HTML‐tabel, met ruimte voor aantekeningen. We hebben de afgekorte namen van de dagen van de week nodig, die op de eerste rij worden getoond. We tonen de dagen van de maand in de cellen van de tabel. We moeten weten op welke dag de eerste van de maand valt. We moeten weten hoeveel dagen de getoonde maand heeft. Technisch detail: voor de flexibiliteit van de vormgeving met CSS en de nette afsluiting van de tabel, moeten we het aantal dagen te weten dat nodig is om de onderste rij vol te maken. Techniek: we gaan objecten gebruiken! NB U vindt de oefenbestanden bij deze paragraaf in de map \hoofdstuk06\kalender. 7
PHP EN MYSQL de basis
Afbeelding 2.1 Het voorlopige eindproduct.
2.1.2 De klasse KalenderMaand Om de functionaliteit die bij een kalendermaand horen, bij elkaar te houden, de‐ finiëren we een klasse: KalenderMaand. Om te beginnen geven we de klasse twee eigenschappen: jaar en maand, en de methoden om deze te zetten of te la‐ ten zien. We willen onze klasse later uitbreiden en scripts maken om een en ander te testen, daarom maken we een map, kalender, met een submap, versie1. In deze sub‐ map maken we twee bestanden: kalendermaand.php en kalendermaandtest.php.
Let op! De naam van de klasse KalenderMaand is geschreven in “CamelCase’, met twee hoofdletters dus, de K en de M. Dit is volgens de naamgevingsconventie die we in het vorige hoofdstuk hebben uitgelegd. De naam van het bestand kalendermaand.php is in kleine letters, waarbij de naam hetzelfde is als de naam van de klasse. Dit maakt het mogelijk om later van de zogenaamde autoload-functie gebruik te kunnen maken, die het overbodig zou moeten maken om de klassebestanden handmatig in te voegen met include() of require(). Ook dit hebben we in het vorige hoofdstuk besproken.
8
Extra voorbeelden
We maken een klasse die alle functionaliteit over een bepaalde maand bij elkaar houdt. Om te beginnen zal een object van de klasse KalenderMaand het jaar en het maandnummer moeten weten. Het allersimpelste begin is dan zó: jaar = $jaar; $this->maand = $maand; } // Blijkbaar is er niets gezet, zet het huidige jaar en maand. else { $this->jaar = idate('Y'); $this->maand = idate('m'); } } } public function __toString() { return 'KalenderMaand, jaar: '. $this->jaar. ' maand: '. $this->maand; } } ?>
We zien dat er twee properties zijn: $maand en $jaar en dat we deze, als we een object creëren, als parameter kunnen meegeven. In de methode __contructor()worden de argumenten (die toevallig dezelfde naam hebben, om u in verwarring te brengen), aan de properties toegekend. Er zijn echter een paar mogelijkheden waar we op moeten testen: het zou kun‐ nen dat er geen argumenten worden meegegeven en in dat geval willen we de huidige maand tonen. Verder zou het kunnen dat iemand wel een jaar maar geen maand meegeeft, in dat geval hebben we een probleem en daarom gooien we een exception, die we straks in het script dat een object probeert te maken weer moeten opvangen.
OEFENING 2.1
MEER CHECKS IN DE CONSTRUCTOR
Eigenlijk zouden we in de constructor ook moeten testen of er wel een geldig jaar- en maandnummer wordt meegegeven. Voor het jaarnummer zou dat binnen de grenzen
9
PHP EN MYSQL de basis
voor een unix-timestamp moeten vallen (lees de opmerking hierover in www.php.net/ manual/en/function.mktime.php) en voor het maandnummer, een nummer van 1 tot 12. Voeg deze code toe in de constructor-methode. Verder ziet u in de klassedefinitie van KalenderMaand een methode met de naam __tostring(). Dit is een zogenaamde magische methode, wat u kunt zien aan de __, net als __construct() natuurlijk. Deze methode is handig om een string‐ representatie van het object te kunnen laten zien. We zullen dit zo dadelijk in ons testscript gebruiken. De definitie van onze klasse KalenderMaand is nog verre van compleet, maar om niet door de bomen het bos niet meer te zien, laten we het hier even bij.
2.1.3 Een testscript voor de klasse KalenderMaand Om te kunnen zien of onze definitie tot zover klopt, maken we een testscript. Dit is een goede gewoonte in de programmeerwereld. We spreken meestal over een unit‐ test, omdat we de test onderverdelen in kleine units en niet de hele toepassing tegelijk proberen te testen. "; try { $kal = new KalenderMaand(); echo "Nieuwe KalenderMaand met nu: $kal\n"; $kal = new KalenderMaand(2012, 7); echo "Nieuwe KalenderMaand met 2010, 7: $kal\n"; $kal = new KalenderMaand(2009); echo "Nieuwe KalenderMaand met 2009: $kal\n"; } catch (Exception $e) { echo 'Er is iets fout met het aanmaken van een KalenderMaand object: ', $e -> getMessage(), "\n"; } echo ""; ?>
De uitvoer van dit script is helemaal als verwacht: Tot zover loopt onze ontwikkeling prima, na een oefeningetje gaan we verder. Om‐ dat we willen bewaren wat we tot nu toe gedaan hebben, maken we een nieuwe submap van de map kalender, en noemen hen versie2. Kopieer alle versie1 bestanden er naartoe.
10
Extra voorbeelden
Nieuwe KalenderMaand met nu: KalenderMaand, jaar: 2011 maand: 12 Nieuwe KalenderMaand met 2010, 7: KalenderMaand, jaar: 2010 maand: 7 Nieuwe KalenderMaand met sept. 1944: KalenderMaand, jaar: 1944 maand: 9 Er is iets fout met het aanmaken van een KalenderMaand object: Als jaar is gegeven, dan moet ook maand gegeven worden.
OEFENING 2.2
MEER TESTS IN HET TESTSCRIPT
Probeer een ongeldige datum en kijk wat er gebeurt. Pas uw checks aan indien nodig.
2.1.4 De verkorte namen van de week De verkorte namen van de weekdagen staan als koppen boven de tabel. Om ze te maken kunnen we een array definiëren: $weekdag = array ('zo', 'ma', 'di', 'wo', 'do', 'vr', 'za');
Als u zeker weet dat alleen Nederlands sprekende gebruikers naar uw kalender zullen kijken dan is dit goed genoeg. Maar natuurlijk willen we de mogelijkheid open houden om de locale te laten variëren en de kalender bruikbaar te maken voor andere talen. U zou het volgende kunnen doen: Met strftime() en de formaatstring %a kunt u de plaatselijke verkorte week‐ dagnaam vinden van de datum die u definieert. Begin op zondag, en dus een datum waarvan u zeker weet dat het een zondag is, 5 juni 2005 bijvoorbeeld. Maak een for‐lus die 7 keer telkens de volgende dag maakt, en de gevonden weekdagnaam in een volgend element van de array stopt. Plaats de code als methode in onze klasse KalenderMaand. protected function setWeekdagen() { for ($i = 0; $i < 7; $i++) { $this -> weekdag[] = strftime("%a ", mktime(0, 0, 0, 6, $i + 5, 2005)); } }
U ziet $this -> weekdag[]..., wat er op duidt dat we een nieuw prop‐ erty hebben gemaakt: protected $weekdag; We maken de methode protected, omdat we niet willen dat deze methode van buitenaf wordt aangeroepen.
11
PHP EN MYSQL de basis
Omdat we de weekdagen maar één keer hoeven te vinden, voegen we een in‐ structie toe aan het eind van de methode __constructor(): $this>setWeekdagen();
OEFENING 2.4
PRINT DE VERKORTE WEEKDAGNAMEN
Print de gevonden weekdagnamen netjes uit. Probleempje: u kunt van buitenaf niet bij de weekdagnamen. Maak als oplossing een publieke methode getWeekdagen();.
2.1.5 Bereken de eerste dag van de maand In ons object van het type KalenderMaand hebben we en jaarnummer en een maandnummer als properties staan. We kunnen mktime() gebruiken om een Unix‐tijdstempel te maken van de eerste dag van de huidige maand: $eerste = mktime(0, 0, 0, $maandnr, 1, $jaar);
En we gebruiken weer idate(), nu het ‘w’ -formaat, om het dagnummer van die eer‐ ste dag te vinden: $edag = idate('w', $eerste);[eind code]
Bijvoorbeeld: in juni 2005 valt de eerste dag op een woensdag en zal $edag de waarde 3 bevatten.
OEFENING 2.5
MAAK EEN METHODE EERSTEDAGINMAAND()
Om de code in de klasse KelenderMaand overzichtelijk te houden is het handig om een methode te definiëren die het dagnummer van de eerste dag in de maand teruggeeft. protected function eersteDagInMaand() { // . . . return $edag; }
Vul de functie in.
OEFENING 2.6
MAAK EEN METHODE DAGENINMAAND()
De methode om het aantal dagen in een maand te berekenen lijkt erg op de functie eersteDagInMaand(). Maak deze methode. Mocht u problemen hebben met een van deze twee oefeningen, spiek dan in de online code, in versie 2 van de klasse KalenderMaand.
12
Extra voorbeelden
2.1.6 De restdagen Hoeveel lege hokjes moeten we aan het begin en aan het eind van onze maand‐ kalender maken om de rijen vol te maken? De berekening gaat zo: protected function restDagen($edag, $ldag) { $mm = ($edag + $ldag) % 7; if ($mm != 0) $mm = 7 - $mm; return $mm; }
Wat hier staat is dat we het aantal lege hokjes aan het begin optellen bij het aantal dagen in de maand. (Het aantal lege hokjes aan het begin is evenveel als het gevonden dagnummer met de functie eersteDagInMaand(), zondag=0, maandag=1, et cetera) Dan berekenen we hoeveel we overhouden als we daar zo vaak als mogelijk 7 van aftrekken. Dit is de modulo‐operator %. Als de uitkomst 0 is dan zijn er geen resthokjes. Anders trekken we de uit‐ komst (in $mm) van 7 af en we hebben het gevraagde aantal. Ook dit stukje code plakken we als methode in onze KalenderMaandklasse. Voorbeeld: uit afbeelding 2.1 blijkt dat er 31 dagen zijn in december 2011 en dat 1 december op donderdag valt (dag 4). Dus: $mm = (4 + 31) % 7 = 35 % 7 = 0, want 5*7 is 35, dus er zijn geen restdagen aan het eind van deze maand. Aan af‐ beelding 2.1 te zien, klopt dit.
OEFENING 2.7
VOEG DAGNUMMER TOE AAN DE KLASSE KALENDERMAAND
Eigenlijk is het onhandig dat we het dagnummer niet weten als de maand waarvoor we een object van het type KalenderMaand maken, de huidige maand is. Doe er iets aan! 1 2 3
Maak een nieuw property voor dag. Voeg een regel aan de __constructor()-functie toe die het property zet (maar alleen als vandaag binnen de huidige maand valt). Pas de functie __toString()aan.
2.1.7 We testen ons werk Laten we eens kijken of onze methoden goed werken. De methoden dagenIn‐ Maand(), eersteDagInMaand() en restDagen() zijn protected, we moeten dus een publieke methode maken om ons werk te laten zien:
Deze methode lijkt wel een beetje op de methode __toString()die we eerder gema‐ akt hebben, ik neem aan dat dit verder geen uitleg behoeft. En nu nog een testscript, dat we gewoon weer kalender-test1.php noemen: "; try { $kal = new KalenderMaand(); } catch (Exception $e) { echo 'Er is iets fout met het aanmaken van een KalenderMaandobject: ', $e -> getMessage(), "\n"; } echo $kal, " "; echo $kal->kalenderInfo(), " "; ?>
Voor 4 december 2011 krijgen we hieruit: KalenderMaand, jaar: 2011 maand: 12 dag: 4 eerste dag: 4, aantal dagen: 31, rest dagen: 0 Kijk maar op een kalender om te zien dat het klopt. Misschien verbaast het u dat zowel het dagnummer als de eerste dag een 4 is. Maar dat komt natuurlijk omdat 1 december in dat jaar op donderdag valt en donderdag de vijfde dag in de week is, waarbij zondag dag 0 is.
2.1.8 Een tabel met dagnummers We zijn nu klaar om de eigenlijke tabel te maken. We maken er meteen een methode in onze klasse Kalendermaand van. public function printMaand() { $edag = $this -> eersteDagInMaand(); $ldag = $this -> dagenInMaand(); $rest = $this-> restDagen($edag, $ldag);
We beginnen met de berekening van de eerste dag, het aantal dagen en de rest‐ dagen. Daarna beginnen we met een HTML‐tabel, met als eerste rij de weekdagenna‐ men in verkorte vorm, die we in onze property $weekdag hebben staan. In de tweede lus, een for‐lus, stappen we door het totaal van het eerste dagnummer, het aantal dagen en het aantal restdagen. Als het goed is, is dit een veelvoud van 7. 1 Print een leeg hokje als de lusteller kleiner is dan het eerste dagnummer (omdat zondag 0 is, gaat dit precies goed). 2 Print ook een leeg hokje (het of‐teken is ||) als we het laatste dagnummer al hebben geprint en de lus‐teller dus groter of gelijk is aan de som van het eer‐ ste dagnummer en het aantal dagen. 3 Als we geen leeg hokje printen, dan printen we het dagnummer. De lusteller is bij het eerste cijferhokje al gelijk aan het dagnummer van de eerste van de maand, dus als we dat getal van de lusteller aftrekken dan staan we op 0. We moeten nu op 1 uitkomen, dus de formule is $i ‐ $edag + 1. 4 Voorbeeld: de lusteller staat al op 3 als we bij de woensdag zijn aangekomen waarop 1 juni 2005 valt. Dat was dagnummer 3, omdat we bij zondag op 0 beginnen. Dus de formule is 3 ‐ 3 + 1. 5 Na zeven hokjes sluiten we de rij af en beginnen aan de volgende. 6 Ten slotte sluiten we de laatste rij en de tabel af.
2.1.9 We testen ons werk We maken een nieuw testscript, kalender-test2.php en we maken ook een .css‐ bestand om de tabel er een beetje beter uit te laten zien.
15
PHP EN MYSQL de basis
We beginnen met het testscript: PHP Kalender
", $kal->printTitle(), "\n"; $kal -> printMaand(); } catch (Exception $e) { echo 'Er is iets fout met het aanmaken van een KalenderMaand object: ', $e -> getMessage(), "\n"; } ?>
We hebben er nu een net HTML‐document van gemaakt. Dat stelt ons in staat een CSS‐bestand in te voegen, kalender.css. De eigenlijke PHP‐code is maar heel kort, alles wat kennis vereist over kalenders hebben we verstopt (Engles: encapsu‐ lated) in de klasse Kalendermaand en de vormgeving zit opgesloten in kalender.css. Ik neem aan dat er weinig uitleg nodig is voor dit script. Merk op dat de PHP‐code ergens middenin het HTML‐document begint. De CSS valt buiten het bestek van dit boek. Een opmerking: Er staat nergens in de CSS hoe breed de tabel‐cellen zijn. Dat ze toch netjes uit elkaar komen te staan is te danken aan de class="wday" toevoeging in de eerste regel met de weekdagen. Probeer maar eens in het CSS‐bestand .wday te veranderen in .wdayx om te zien wat er gebeurt. Als het goed is, is uw resultaat zoiets als afbeelding 2.1.
OEFENING 2.8
HIGHLIGHT VANDAAG
Print de huidige maand met daarin het dagnummer van vandaag in rood, of vet gedrukt.
16
Extra voorbeelden
OEFENING 2.9
PRINT 12 MAANDEN VANAF NU
Maak een for-lus die in twaalf stappen de twaalf maanden vanaf de huidige maand afdrukt. Check of de jaarovergangen en maandovergangen goed verlopen.
2.2 De klasse TableView Alles werkt nu zoals het hoort, maar de oplettende lezer heeft vast enkele tekort‐ komingen in onze klasse KalenderMaand ontdekt. Het geen goed gebruik om inhoud met vormgeving te mengen, zoals we gedaan hebben in de methode printMaand(). Stel dat we een agenda zouden willen maken met een meer ingewikkelde HTML‐structuur en grote hokjes waar tekst in kan staan. Stel dat we de kalender op de Nederlandse manier zouden willen printen, namelijk de weekdagen links onder elkaar en eventueel weeknummers bovenin. De HTML in onze tabel is nogal knullig. De eerste rij met weekdagnamen zou beter in
tags gevat kunnen worden en om de tabel te kunnen gebruiken voor dyna‐ mische vormgeving hebben we ook - en
-tags nodig. Om dit op te lossen ontkoppelen we de HTML van de klasse KalenderMaand en maken we een nieuwe klasse die we TableView dopen. Voordat we verder gaan, maken we een nieuwe map, versie3 en we kopiëren de bestanden uit versie2 hier naartoe. We besluiten tot een ontwerp van de klasse TableView als volgt: De klasse TableView heeft één argument, een associatieve array met elemen‐ ten ‘thead’ en ‘tbody’. Eventueel kunnen we dit later uitbreiden met een ‘id’ en een ‘class’ en misschien meer. De tabel‐header is een array met kolomnamen. De meest logische invoer voor de tabel‐body lijkt ons een tweedimensionaal array te zijn. Dit resulteert in de volgende code: thead = $table['thead']; $this->tbody = $table['tbody']; } // … hier komt de methode printTable
17
PHP EN MYSQL de basis
} ?>
Zoals u ziet gebeurt er in de constructor niets anders dan het uit elkaar halen van de array die als argument is meegekomen. public function printTable() { echo "\n", '
De methode printTable() is erg eenvoudig. In twee foreach()‐lussen worden eerst de header en daarna de rijen geprint. Voor iedere rij is er een derde foreach()‐ lus die elk veld van de benodigde
tags voorziet. Misschien vindt u deze klasse ook nog vrij simpel; zoals gezegd, we zouden het mogelijk kunnen maken een id of een class toe te voegen. En we zouden wat kunnen doen aan het opvangen van fouten. Maar we hebben hiermee een zeer belangrijke loskoppeling gemaakt van de klasse KalenderMaand (hoewel we daar nog wel iets aan moeten doen).
OEFENING 2.10
GEBRUIK DE TABLEVIEW
Maak een array met een paar rijen en een header. Print hem uit met de TableView.
2.2.1 Wijzigingen aan de KalenderMaand klasse Nu we onze TableView hebben, moeten we de HTML die in de klasse Kalender‐ Maand wordt gemaakt er weer uit slopen. We moeten een tabelstructuur bedenken die we aan kunnen bieden aan de TableView. We gaan dit in twee stappen doen: Maak een methode asArray(), die een array retourneert waarbij in de lege hok‐ jes een lege string staat en in de andere hokjes het dagnummer. Maak een methode kalenderUSStyle() die de dagen in rijen organiseert, zodat er een kalender uitkomt zoals gebruikelijk in Angelsaksische landen en zoals afge‐ beeld in afbeelding 2.1
18
Extra voorbeelden
OEFENING 2.11
MAAK DE METHODEN ASARRAY() EN KALENDERUSSTYLE()
Met alle uitleg die we al eerder hebben gegeven zou u deze methoden moeten kunnen maken. Maar spieken is toegestaan. Opmerking: ook een kleine aanpassing aan de CSS is gemaakt, zie het CSS‐bestand in de versie3 map. Natuurlijk hebben we nog een testscript nodig, we zullen niet het hele script laten zien, maar de belangrijkste regels: getMessage(), "\n"; exit ; } echo "
De code zal u inmiddels bekend voorkomen. Overtuig u er nogmaals van dat de kalen‐ der er zo uit ziet als in afbeelding 2.1.
OEFENING 2.12
MAAK DE METHODE KALENDERNLSTYLE()
Deze oefening is niet zo makkelijk, omdat u de arrays moet samenstellen uit niet opeenvolgende elementen. En het zou leuk zijn als de weekdagennamen links worden getoond met enige highlighting.