Graag zou ik willen weten of ik in de juiste richting zit te denken.
Vanuit mijn database maak ik opties aan voor in de select, zodat gebruikers alleen daar de keus uit hebben.
Natuurlijk wil je niet dat via de inspector de waardes alsnog kunnen worden aangepast.
Ik wil dus een controle of de waarde ook overeenkomt met de lijst uit de database.
Is het dan verstandig als het formulier geladen word eerst de waardes in een array te zetten en met een foreach loop de opties aan te maken en de controle te doen met array_key_exists?
Die wel ja. Nog niet gereserveerde tijdslots staan echter nog niet "uitgeschreven" in de DB. En om te voorkomen dat iemand dan maar lukraak een tijdstip kiest (niet op een "rond" kwartier, of buiten de van/tot tijden) zul je toch dit lijstje moeten regenereren.
Je zou het wel om kunnen draaien: eerst kijken of de tijd al gereserveerd is, en pas als dat niet het geval is kijken of de tijd wel is toegestaan.
Je zou natuurlijk ook alle vrije tijdslots alvast in de database kunnen zetten. Nadeel is dat je dan "in het voren" moeten gaan werken (hoe ver?). En als je dan het algemene schema wijzigt moet je ook al dit "voorwerk" weer gaan lopen corrigeren.
Eerst kijken of er gereserveerd is en dan pas controleren of het formaat klopt lijkt mij een beetje suf?
Als het goed is heb je van een dag al de begin- en eindtijd (of dat is een goede query om mee te starten). De gekozen tijd moet hier sowieso binnen vallen. Daarnaast betreft het intervallen van een kwartier. Dit zijn al twee controles op het formaat die je sowieso kunt uitvoeren voordat je (meer) vragen stelt aan de database. Vervolgens zou je nog een laatste query kunnen uitvoeren of het desbetreffende tijdsslot al gereserveerd was. Dit alles zou wel binnen een transactie moeten plaatsvinden lijkt mij, om het gevaar van een dubbele boeking in het geheel weg te nemen.
Volgorde bij verwerking is dus bijvoorbeeld:
- controleer format tijdsslot (intervallen van een kwartier)
--- start voor de volgende stap ergens een transactie ---
- controleer of het tijdsslot binnen het rooster van de gekozen dag valt (query)
- controleer of het tijdsslot vrij is (query)
- schrijf tijdsslot weg
--- beëindig transactie ---
Indien een van de stappen faalt kun je deze hele riedel meteen afbreken.
NB wellicht moet je ook een voorziening hebben dat je kunt controleren of je met een uitzondering in het rooster te maken hebt (bruiloft, overlijden of feestdag oid) waardoor de vestiging niet open is op een bepaalde dag.
?
Onbekende gebruiker
14-09-2020 16:09
gewijzigd op 14-09-2020 16:10
Frank Nietbelangrijk op 08/09/2020 23:39:26
>> Wat zou de use case zijn die de overhead rechtvaardigt?
- Lees Rob zijn reactie nog eens door
[...]
Het verschil zit hem in mijn context. Ik heb wel de database tot eigenaar van de gegevens gemaakt. En het is dan wel zo handig om meteen gebruik te maken van het feit dat de database prima de autorisatie kan waarborgen. Ik heb niet genoeg tijd om dat wiel opnieuw in PHP uit te vinden. Zeker niet als er sprake is van meerdere tabellen met row level security. De database hoeft ook niet de hele tabel door te lopen, hij (of zij?) maakt gebruik van indices waardoor je het eigenlijk niet sneller kunt nabouwen in PHP.
Aangenomen dat je applicatie of website door meerdere mensen tegelijkertijd bezocht wordt kan je die waarden ook niet client-side of PHP side cachen voor controle, omdat die waarde in de tussentijd veranderd kan zijn, daarom zou je de twee stappen (controle en oplaan) binnen een transactie moeten doen.
Het wordt een ander verhaal als je de database behandelt als domme data-opslagplaats (stel, in het geval van MySQL) en via bijvoorbeeld ORM moeilijk gaat lopen doen. Toch is dat een veelgebruikt paradigma, maar het is niet mijn keuze. In een enterprise situatie heb ik liever een slimme database. De applicatie moet er altijd rekening mee kunnen houden dat er nog andere applicaties zijn die met dezelfde gegevens werken.
Wat ik me nog kan voorstellen is dat de database op een andere locatie zit in de infrastructuur, waardoor communicatie tussen PHP en de DB prijzig wordt in termen van netwerk I/O. Maar dan kan je beter die infrastructuur onder de loep nemen, dan iets handmatig in PHP gaan doen waar je een database voor hebt.
Het wordt een ander verhaal als je de database behandelt als domme data-opslagplaats (stel, in het geval van MySQL) en via bijvoorbeeld ORM moeilijk gaat lopen doen.
Interessante woordkeuze.
Ik gebruik zelf geen ORM, maar het feit dat het bestaat wil waarschijnlijk zeggen dat het een toepassing(sgebied) heeft. Net zoals ik mij kan voorstellen dat ORM niet ieders cup-of-tea is, kun jij je misschien voorstellen dat "domme data-opslag" in veel gevallen (meer dan) afdoende is.
Maakt het nu echt uit waar validatie geschiedt voordat het de database in gaat? Bekommer je je dan niet meer om de vorm dan om het daadwerkelijke doel? Als het maar gebeurt, en zolang het maar consistent gebeurt, lijkt mij.
Ik denk ook niet dat de gemiddelde bezoeker hier op zoek is naar enterprise-oplossingen, die kennis en technieken zul je waarschijnlijk ergens anders moeten verwerven en dat vergt ook een stuk meer (gestructureerd) werk voor de persoon in kwestie.
Dit alles zou wel binnen een transactie moeten plaatsvinden lijkt mij, om het gevaar van een dubbele boeking in het geheel weg te nemen.
Een transactie werkt hier niet omdat deze locken op row(record) level en een nieuw record (nog) niet bestaat en dus ook niet gelocked kan worden.
In dit geval kan je beter met lock tables werken.
Als er een unique constraint op de "boeking" tabel zit gaat het toch goed: "nummer 2" krijgt een error/exception in z'n mik omdat de insert mislukt (key bestaat al). Vervolgens draai je in de error handler de transactie terug.
?
Onbekende gebruiker
16-09-2020 10:04
gewijzigd op 16-09-2020 10:09
Thomas van den Heuvel op 14/09/2020 17:22:01
Maakt het nu echt uit waar validatie geschiedt voordat het de database in gaat? Bekommer je je dan niet meer om de vorm dan om het daadwerkelijke doel? Als het maar gebeurt, en zolang het maar consistent gebeurt, lijkt mij.
Ik denk ook niet dat de gemiddelde bezoeker hier op zoek is naar enterprise-oplossingen, die kennis en technieken zul je waarschijnlijk ergens anders moeten verwerven en dat vergt ook een stuk meer (gestructureerd) werk voor de persoon in kwestie.
Ik kan me toch niet helemaal aan de indruk onttrekken dat bezoekers op deze site wel eens gewezen worden op gestructureerd werken en de betere oplossingen. En dat onderschrijf ik, want als je er moeite voor doet, loont het om het programma zo elegant mogelijk te maken. Je weet immers niet wanneer je nog eens met je eigen code geconfronteerd wordt.
En validatie moet inderdaad consistent gebeuren.
Ik heb het plezier gehad om jarenlang met MySQL te mogen werken. En daarbij heb ik vaak gedacht: 'waarom is dat nou niet gewoon goed geregeld in MySQL?'. Simpele dingen als een tijd opslaan met tijdzone, of dat een query ongemerkt niet klopt omdat er ergens een automatische cast heeft plaatsgevonden wat elk normaal mens ontgaat.
Toegegeven, je kunt in technisch opzicht alles bouwen met MySQL, inclusief de dingen die andere databases al lang hebben. Maar dat kost extra tijd. Ik denk dat dit de reden is waarom MySQL vaak gebruikt wordt als 'domme data-opslagplaats', aangevuld met ORM.
ORM doet wat andere databases doen, waarbij de controle plaatsvindt in PHP. Handig voor wie PHP machtig is, maar waarom zou je niet gewoon de native (en goedkopere) functionaliteit van de database benutten die er al is? Als ik zie dat bijvoorbeeld Doctrine metadata van data uit de database opslaat in de PHP comments, dan denk ik dat het wel een heel omslachtige manier is om gestructureerd te werken.
Kortom: alles wat je met data doet, kan sneller en beter in een database.
Beter, omdat je problemen vermijdt, zoals verkeerd gebruik van PHP string-functies die geen multibyte encoding zoals UTF-8 ondersteunen. Beter, omdat je bij de bron validatie en autorisatie kunt afdwingen, zodat je dat niet op meerdere punten moet doen wanneer je programma wordt gesplitst of als er meerdere applicaties bij komen die met de data moeten werken. Eleganter omdat het meer conform SRP is, dat dit alles al geregeld is nog voordat PDO verbindt met de database.
Als je dingen gewoon kunt inregelen in de database, ga dat toch niet opnieuw programmeren in PHP? Ik begrijp dat er historische redenen voor kunnen zijn, maar als we dan toch bezig zijn om het goede voorbeeld te geven vind ik dat we moeten stellen dat gegevensvalidatie het beste in de database kan plaatsvinden.
Interessante discussie ... ik lees even mee ... :)
@ Ad Fundum
>> ... vind ik dat we moeten stellen dat gegevensvalidatie het beste in de database kan plaatsvinden.
Over wat voor gegevensvalidatie heb je het nu precies?
Je kunt in een database inderdaad veel regels vastleggen, en dat mag. Of het ook "het beste" is, hangt van je manier van werken af en van bepaalde verwachtingen. Heel zwart-wit, jij ziet een database als "beheerder" van je data. Een soort van applicatielaag die bepaalt wat wel en niet mag. Thomas ziet een database als simpele/domme opslagbron waar je data in stopt en weer uithaalt. Voor beiden valt iets te zeggen.
Ik denk echter niet dat je zomaar kunt stellen dat "gegevensvalidatie het beste in de database kan plaatsvinden". Dit hangt van je toepassing en (toekomst)verwachtingen af.
Je kent vast wel het principe in OOP dat je componenten makkelijk moet kunnen omwisselen. Dat geldt ook voor de opslag van data. In theorie zou je in een op OOP gebaseerde applicatie binnen 5 minuten van type database moeten kunnen wisselen, simpelweg door de huidige database class te vervangen door een nieuwe database class die communiceert met de nieuwe database. (Dit is de theorie. In de praktijk zul je misschien her en der nog wat queries moeten aanpassen.)
Stel dat we uitgaan van de database als domme opslagplaats dan gaat het bovengenoemde op. Ga je uit van de database als "beheerder" van data, dan heb je een probleem. Je zult alle regels die voorheen in de oude database waren ingesteld, moeten gaan overzetten naar de nieuwe database ... als die überhaupt over die mogelijkheden beschikt.
Laten we het nog wat gekker maken. Je wilt de data niet langer opslaan in een database, maar (om welke reden dan ook) in een tekstbestand. Nu heb je een probleem, want in een tekstbestand kun je geen regels toepassen. Je verliest daarmee dus je controle. Nu is dit niet een heel reële situatie, maar het gaat even om het principe.
Wat ik wil zeggen, is dat wanneer je dingen in een database gaat 'programmeren' je vastzit aan die database. De database is dus als het ware een vast, niet-uitwisselbaar, onderdeel geworden van je applicatie.
In het geval van de domme database stop je alle controles en validaties in PHP en weet je dat die altijd hetzelfde zijn en altijd zullen werken, ongeacht welke database of andere opslagmethode je eraan hangt.
Voor beide oplossingen valt wat mij betreft iets te zeggen. Waar je voor kiest hangt van je toepassing af. Kun je goed met PHP overweg en wil je ultieme controle in elke situatie, dan voldoet de database als domme opslagbron prima. Heb je een applicatie die vooral database driven is en waar vele partijen hun data uithalen, dan kan een 'geprogrammeerde' database uitkomst bieden. Je moet dan wel zeker weten dat je die betreffende database jarenlang gaat gebruiken en niet tussentijds gemakkelijk kunt wisselen. Daarnaast kun je je afvragen of al die externe partijen zomaar in jouw database moeten kunnen roeren, en of je in een dergelijke situatie niet veel beter een API hiervoor kunt inzetten waarin tevens de controles plaatsvinden.
Anyhow ... dit is hoe ik er tegenaan kijk.
?
Onbekende gebruiker
16-09-2020 13:22
gewijzigd op 16-09-2020 13:24
Ozzie PHP op 16/09/2020 11:27:01
Over wat voor gegevensvalidatie heb je het nu precies?
[...]
Je kent vast wel het principe in OOP dat je componenten makkelijk moet kunnen omwisselen. Dat geldt ook voor de opslag van data.
[...] wanneer je dingen in een database gaat 'programmeren' zit je vast aan die database. De database is dus als het ware een vast, niet-uitwisselbaar, onderdeel geworden van je applicatie.
Met gegevensvalidatie bedoel ik de juistheid van de gegevens. Of een foreign key geldig is, of een string niet te lang is en aan een bepaalde vorm voldoet, of een datum binnen een bepaalde termijn valt. Dat soort dingen.
Dat tegenargument had ik ook verzonnen, maar het gaat niet op. Want dat zou dan ook moeten gelden voor PHP, en het besturingssysteem.
Ik zit serieus te kijken om mijn PHP programma om te bouwen in Rust, maar dat zal nog lastig worden. Het is nog eenvoudiger om mijn PHP programma om te bouwen naar Windows, maar dat is meer met dank aan PHP. Van PHP kom je niet snel 'af' als je dat zou willen omwisselen. Misschien kan ik het beter omschrijven naar Haxe, dan kan je PHP wel net zo gemakkelijk verwisselen als een database.
Gelukkig kan je Linux nog eenvoudig draaien op een ander besturingssyteem, al dan niet gevirtualiseerd. Maar het blijft linux.
Ook databases kennen die optie: je kunt bijvoorbeeld via ODBC (langzamere) verbindingen maken met andere databases en daarvan data gebruiken.
'Waarom zou het belangrijk zijn om PHP in te kunnen wisselen?' zou je je kunnen afvragen. Dat is vrij simpel: PHP wordt onderhouden door vrijwilligers die zich voor maximaal 3 jaar aan een PHP-versie verbinden. Daarna krijg je geen ondersteuning meer op het gebied van beveiliging.
Dus als je je met een PHP programma wilt kunnen verbinden aan een klant, doe je een belofte die gebaseerd is op je eigen verwachting. En dat is soms best spannend, bijvoorbeeld na PHP 5.6 duurde het even voordat PHP 7 kwam.
Ter vergelijk: de database die ik gebruik (PostgreSQL) kent een ondersteuningstermijn van 5 jaar.
Dan zou je toch eerder de vraag moeten stellen hoe PHP in te wisselen.
Voor de duidelijkheid: ik ben ondanks de vele valkuilen van PHP nog steeds fan van PHP, zeker nu versie 8 er aan zit te komen.