Orde in PHP
Home

Orde in PHP

Orde in PHP

OO is helemaal niet voor blaaskaken, om gewichtig te doen.

Probleem

Ik heb hier een mooi voorbeeld van waarop OO ooit is bedacht. In bijlage vind je de code uit een bachelor cursus PHP tweede jaar. Wat is het probleem in deze code?

Design

Functionele vereisten

Het aanmelden opdelen in op zichzelf staande onderdelen ook wel primitieven genoemd. Een primitief is een zelfstandig benoembare handeling die op zichzelf getest kan worden. Dat ligt in de richting van SOC (speration of concerns), het SRP (single responsabilty principle), één van de SOLID design patronen en het DRY (don't repeat your self) principe. Enfin dit laatse vloeit automatisch voort uit de twee voorgaande.

We beginnen met het opsommen van de primitieven:

  1. een definitie van een gebruiker
  2. gegevens van een gebruiker persistent maken:
    1. registreren, definitief in een database;
    2. tijdelijk in een sessie, cookie;
  3. gegevens van een gebruiker opzoeken in:
    1. database;
    2. session/cookie;
  4. intypen van gebruikersgegevens
  5. intypen van logingegevens
  6. paswoord encrypteren
  7. paswoord verifiëren
  8. email verifiëren

Domein

We leggen eerst ons domeinmodel vast. Met welke gegevens uit het domein moeten we werken?

User klasse velden
Naam Gegevenstype National Beschrijving
name text YES gebruikersnaam
email text NO email adres van de gebruiker
password text NO geëncrypteerd paswoord
lastActivity datetime wanneer heeft de gebruiker zich het laatst aangemeld
createdOn datetime wanneer heeft de gebruiker voor de eerste keer zich aangemeld
createdBy text YES wie heeft de gebruiker aangemaakt
updatedOn datetime wanneer zijn de gebruikersgegevens voor het laatst gewijzigd
updatedBy text YES wie heeft de gebruikersgegevens het laatst gewijzigd

De User klasse beschikt over getters en setters voor alle velden. Daarnaast hebben we nog enkele specifieke methoden nodig.

User klasse methoden
Naam Parameters Return type Beschrijving
create geen int insert de gegevens die al in de velden staan in de User tabel en retourneert true als de insert gelukt is, anders false
readByEmail int zoekt de rij met de opgegeven email op en retourneert true als rij gevonden, anders false
readByName int zoekt de rij met de opgegeven name op en retourneert true als rij gevonden, anders false
__construct we maken een verbinding in de constructor
__destruct we verbreken de verbinding

De velden zijn niet moeijlijk te maken:

De getters en setters zijn voorlopig uiterst eenvoudig. De validatie doen we later.

In de constructor maken we een verbinding met de MySQL server. We gebruiken hiervoor de PDO klasse. Het leggen van de verbinding staat in een try catch blok om:

  1. het programma niet laten vastlopen als er iets niet in orde is met SQL server
  2. meer info te krijgen over wat er eventueel niet in orde is; daarvoor gebruiken we de PDOException klasse.

In de create methode staat de execute methode in een try catch blok.

Maar dat vangt de eventuele foutmeldingen, die van MySQL komen, niet op. Maar dat is heel moeilijk te debuggen. Als er fout in het SQL statement staat (bijvoorbeeld een verkeerde kolomnaam) loopt de code gewoon door. Execute retourneert wel false maar we weten bij god niet waarom.

Daarom is het nuttig de retourwaarde van de errorInfo methode van het prepared statement object te bekijken.

En dan stoot je gelijk op een ander probleem. Hoe ga je die info aan de view doorgeven? Je kan dit gauw gauw met een var_dump doen maar veel netter met een feedback systeem. Kijk bijvoorbeeld eens naar het feedback systeem van Dialog.

Nog een verbeterpunt is de manier wordt het SQL statement aan MySQL wordt doorgegeven. Het is al goed dat de waarden voor de insert en de select statements als parameters worden doorgegeven. Maar ik zou nog een stap verder gaan en geen SQL statement vanuit PHP doorsturen maar een de naam van een op de server uit te voeren stored procedure.

Interactie

Knoppen staan op formulieren, al een geluk. Maar de code, die de interactie met de gebruiker afhandelt, staat werkelijk overal versnipperd. Heel wat redirects waarmee je van her naar der springt. Redirects raad ik af want moeilijk te debuggen. De afhandeling van de interactie staat waarlijk overal en nergens. Hoe kan je in godsnaam de workflow volgen? Is het geen idee om alle interactie met de gebruiker op één plaats te centraliseren in wat in het MVC patroon, de controller wordt genoemd? We maken één enkele switch die alle interactie met de gebruiker afhandelt.

Een eerste stap op de goede weg bestaat er in het html button element te gebruiken i.p.v. het input type submit html element. Immers voor elk input type submit element moet je een andere waarde toekennen aan het name attribuut. Om te weten als er op een submit input knop geglikt werd moet je isset() gebruiken en als parameter de waarde meegeven van het name attribuut van het submit input element. Als je het button element gebruikt kan je dezelfde techniek gebruiken als voor radio buttons en toch nog een andere tekst laten zien aan de gebruiker.

Een tweede stap, is het opstellen van use cases. Je gaat zien dat met elke use case een knop overeenstemt. Ik heb het niet over systeem use cases maar over gebruikers use cases.

JI
2016-01-04 15:08:05