Controle op input van database waardes
Hoe je dit echter opslaat is een ander verhaal. Dit formaat moet zo gekozen worden dat je dingen in de bovenstaande aanpak kunt veranderen zonder dat deze zijn weerslag heeft op de structuur van je data (je moet er toch niet aan denken dat je alle code voor de aansturing van queries om moet gooien omdat je daarin iets wijzigt?) en ook zou deze zo gekozen moeten worden zodat je hier makkelijk mee kunt rekenen. Standaard typen hebben een heleboel functionaliteit en zijn ook voor het rekenwerk geoptimaliseerd. Een custom formaat heeft deze rechtstreekse ondersteuning vanuit de database niet of de mogelijkheden zijn daardoor op voorhand heel erg beperkt. Het is simpelweg geen slim databaseontwerp als er andere, beter gangbare alternatieven beschikbaar zijn.
Dat heb ik dan blijkbaar gemist. Hoe zou jij dan een value voor een tijdvak samenstellen?
Er zijn eindeloos veel manieren om dit vorm te geven, kies er een. En zoals ik hierboven ook al typte: je zou bijvoorbeeld simpelweg een blokje met een tijd, gegroepeerd op dag, kunnen kiezen, en dat reeds gekozen tijdsvakken in een soort van "inactieve" staat verkeren. Of spiek gewoon bij andere systemen hoe dit er uitziet. Maakt het uit?
Ook hoe dit er onder de motorkap uitziet? Take your pick? Genoeg fancy mogelijkheden met CSS en JavaScript. Maakt niet uit hoe het formulier werkt, met JavaScript krijg je dit hoe dan ook aan elkaar gemetseld met de backend. Je kunt alle informatie (dag + tijden) simpelweg bij elkaar harken tot volledige datetime-timestamps en deze vervolgens doorsturen.
Ik zou aab de serverkant waarschijnlijk werken met de DateTime-classes. Daarmee kun je makkelijk datums en tijden uitrekenen. Dit is gewoon aan de molen draaien met een for-loop?
Maar eerst zul je een idee moeten hebben hoe dit er uitziet. Begin bij het einde. Ik kan niet beginnen met code breien en dat daar uiteindelijk een kous uitkomt. Je moet ergens naartoe werken - je moet het idee hebben om een kous te breien, hier vervolgens een breipatroon bij zoeken en dan pas gaan breien. Niet andersom. Ik weet dus niet helemaal wat je van mij verlangt. Mijn eerste vraag als iemand om zulke functionaliteit vraagt zou waarschijnlijk zoiets zijn als: "Heb je hier een idee over hoe je dit er uit wilt laten zien?". En dit kan best afwijken van de data die op de achtergrond aan opgehangen is, dit staat los van elkaar.
Uiteindelijk stop je dit in een of meer DATETIME-kolommen in je database om simpelweg je opties open te houden, bijvoorbeeld een voor de begintijd en een voor de eindtijd zodat deze samen een tijdsvak vormen.
Weet niet helemaal wat ik nu nog mis?
Gewijzigd op 17/09/2020 01:18:24 door Thomas van den Heuvel
Ik ga dus uit van tijdvakken tussen bijv. 14.00 en 16.15 uur op donderdag 17 september 2020.
Je zou dan dus een drop down kunnen tonen met:
14.00-14.15
14.15-14.30
...
16.00-16.15
Als iemand dan een optie selecteert, moet je serverside weten welke optie het is. Zodoende mijn idee om daar een value 2020091714001415 aan te koppelen. Jij hebt daar vervolgens commentaar op (dat mag). Dan vraag ik hoe jij die value zou genereren en komt er een heleboel tekst, maar geen voorbeeld.
Ozzie PHP op 17/09/2020 01:32:42:
Zodoende mijn idee om daar een value 2020091714001415 aan te koppelen.
Wat is daarvan het voordeel? Als de duur altijd een kwartier is, hoef je alleen de begintijd van een afspraak te weten.
Dat kan ook nog efficiënter, want er gaan (24 * 60) / 15 = 96 kwartieren in een dag, dus een kleine integer volstaat.
Ozzie PHP op 17/09/2020 01:32:42:
Dan vraag ik hoe jij die value zou genereren en komt er een heleboel tekst, maar geen voorbeeld.
Starttijd (2020-09-17 16:30:00) en eventueel duur (0:15 of een veelvoud hiervan?) zoals @Ward min of meer aangeeft, of als alternatief daarvoor een (volledige) eindtijd (2020-09-17 16:45:00).
Indien het interval vastligt, dan weet je je eindtijd al impliciet. In dat geval hoef je deze informatie ook niet over te hevelen naar de server, een starttijd volstaat dan.
>> Wat is daarvan het voordeel? Als de duur altijd een kwartier is, hoef je alleen de begintijd van een afspraak te weten.
Als het altijd een kwartier is dan inderdaad wel.
@Thomas
>> 2020-09-17 16:45:00
Dus het ging je om het format met streepjes en spaties. Oké. Ik had geen idee wat je bedoelde.
Ward van der Put op 17/09/2020 14:20:09:
dat kan ook nog efficiënter, want er gaan (24 * 60) / 15 = 96 kwartieren in een dag, dus een kleine integer volstaat.
Ward is me net voor!
Ik denk dat er al snel te moeilijk gedacht wordt. Als je PHP als 'piloot' ziet, zie je elk probleem als iets dat je met PHP op moet lossen. (Variatie op: wie een hamer heeft, ziet elk probleem als een spijker)
Het is zinnig om niet alleen code te modelleren volgens alle prettige OOP-richtsnoeren, met gegevens kan dat net zo goed. En als je de SQL beperkt houdt tot ANSI SQL, dan kan je met minimale moeite van database wisselen met PDO.
Omdat de business-case voorschrijft om kwartieren als tijdresolutie te gebruiken, is een tijdtabel handig. Daarna maak je een tijdtabel met de te kiezen tijden per week. In pseudo SQL:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
create table kwartier (nr int, van time, tot time, primary key (`id`));
insert into kwartier values (1, '00:00', '00:15'), (2, '00:15', '00:30'), ... ;
-- ^-> kan in een keer met generate_series()
create table week (dag date, kwartier int, ... , primary key (dag, kwartier));
-- ^-> als je liever 1 id kolom hebt voeg je die toe als PK en zet je een
-- unique constraint op dag, kwartier.
-- Weekdagnummers lopen van 1 voor maandag tot en met 7 voor zondag
insert into week (dag, kwartier)
select 1, nr from kwartier where van >= '12:00' and van < '18:00';
insert into week (dag, kwartier)
select 2, nr from kwartier where van >= '10:00' and van < '18:00';
-- etc.
insert into kwartier values (1, '00:00', '00:15'), (2, '00:15', '00:30'), ... ;
-- ^-> kan in een keer met generate_series()
create table week (dag date, kwartier int, ... , primary key (dag, kwartier));
-- ^-> als je liever 1 id kolom hebt voeg je die toe als PK en zet je een
-- unique constraint op dag, kwartier.
-- Weekdagnummers lopen van 1 voor maandag tot en met 7 voor zondag
insert into week (dag, kwartier)
select 1, nr from kwartier where van >= '12:00' and van < '18:00';
insert into week (dag, kwartier)
select 2, nr from kwartier where van >= '10:00' and van < '18:00';
-- etc.
Daarna kan je in de HTML5 volstaan met een <input type="date">, deze komt met gratis datepicker met een datumformaat dat gelijk is aan SQL.
En natuurlijk een <select>, gevuld met <option>s waarvan het value-attribuut gelijk is aan de PK van kwartier, en de innerHTML kan je vullen met CONCAT(van, ' - ', tot).
De formuliergegevens kan je direct opsturen naar de database zonder validatie in PHP. Omdat de gebruiker alleen maar geldige data in kan voeren, hoef je dus ook geen specifieke foutmeldingen te verzinnen als 'u moet de datum wel goed invoeren met streepjes en voldoende voorloopnullen', ook ongeldige datumcombinaties als '29-02-2021' worden al afgevangen in de browser. De browser houdt rekening met de locale van de gebruiker, nog een zorg minder voor PHP.
En dat is wat ik bedoel met niet opnieuw het wiel uitvinden. Hoe simpeler en doeltrefferender, hoe eleganter. Hoe eleganter, hoe minder tijd je dat kost. Een voordeel voor zowel enterprise programma's als eenvoudiger websites.
Ad Fundum op 18/09/2020 09:15:13:
Omdat de gebruiker alleen maar geldige data in kan voeren
Haha ... "Never Trust Data from the Browser"
De gebruiker kan nog steeds een ongeldige combinatie datum/kwartier invoeren (door een beetje "te klooien" via de inspector). Bijvoorbeeld op een zondag: de datum is van precies het juiste formaat, het kwartier ID komt voor in de kwartier tabel (foreign key). En toch is het niet juist.
Rob Doemaarwat op 18/09/2020 09:26:59:
... "Never Trust Data from the Browser"
Uiteraard heb je daar gelijk in.
Maar je mist mijn punt. Een gewone gebruiker kan alleen maar geldige data invoeren. De browser kan de gebruiker prima assisteren met het invullen van geldige data, dat hoef je niet opnieuw in PHP te doen.
Als er iemand ligt te klooien via de developertools of anderszins, heeft het ook geen zin om betekenisvolle foutmeldingen terug te geven. Je kunt volstaan met een generieke foutmelding of geen reactie. Dat scheelt tijd en moeite.
Natuurlijk moet je niet vergeten om zulke incidenten te loggen.
Het kwartier moet je niet checken met de kwartiertabel, maar met de weektabel. Want daarin staan alleen de geldige kwartieren per weekdag. Je moet in de tabel die de gebruiker vult, wel een enkele foreign key hebben met de kolommen weekdag én kwartiernummer tegelijk, op de weektabel. Dat is de check die de database voor je kan doen, zodat je niets in PHP hoeft te valideren.
Mijn aanname is dat de database geen ongeldige datums op kan slaan. MySQL kan dit wel (lang leve MySQL, *zucht!*) maar je kunt dat vermijden door de SQL_MODE goed in te stellen. Schakel bijvoorbeeld ALLOW_INVALID_DATES uit en zet NO_ZERO_DATE en NO_ZERO_IN_DATE aan. Voor alle leuke details zie: https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html