Back end

Ontwerp

Je hebt vooraf nagedacht over technische keuzes en dit heb je inzichtelijk gemaakt. Je kan je project technisch documenteren middels minimaal twee diagrammen (bijv. ERD, klassendiagram en/of flow chart). Je hebt een bestaande library toegevoegd aan je project om functionaliteiten toe te voegen of om het programmeren makkelijker te maken. Je kunt toelichten waarom dit nuttig is.

Als begin van het maken van een reserveringssysteem is het handig om kort te beschrijven wat je gaat doen. Ik heb dit gedaan door Pseudocode te schrijven met betrekking tot het reserveren.

PSEUDO CODE Reserveren
Klant komt aan op index.php/reserveren.php 
Is er op submit geklikt? 
   /Ja, Is al het benodigde ingevuld? /Ja, Klopt de gegeven informatie?   
      /Ja, Verwijs klant door naar confirm.php met ingevulde data, 
           stuur bevestigingsmail naar klant en admin, 
           zet ingevulde info in database en haal gekozen tijd uit      
           formulier. 
         /Nee, Geef foutmelding. 
      /Nee, Geef foutmelding. 
   /Nee, Doe niks-Laat leeg formulier zien.

Aan de hand van de Pseudocode heb ik een Flow-chart gemaakt om voor mezelf duidelijk te maken waar ik mee bezig ben. Doordat ik best wat moeite heb met PHP, helpen de Flow-chart en Pseudocode om te beginnen met het product te maken. Het houdt me ook gefocust op wat ik nog moet doen.

Om een database te maken heb je tabellen nodig. Om ervoor te zorgen dat ik gestructureerd te werk ga heb ik een ERD (Entity Relationship Diagram) gemaakt van alle informatie die ik ga verzamelen en bewaren.
Ik heb twee tabellen gemaakt. Één voor de reserveringen en de ander voor de admin. Deze twee hebben geen connectie, vandaar dat er geen lijn tussen zit.
Hieronder is te zien hoe dit eruit ziet:

Als library/API heb ik ervoor gekozen om de library phpmailer te gebruiken. Deze library zorgt ervoor dat er een bevestigingsmail gestuurd kan worden na het maken van een reservering. De mail kan je als programmeur naar eigen wil aanpassen. Ik heb deze library van een Github pagina:
Library

Deze pagina heeft me goed geholpen. Naast een uitleg over hoe je deze library moet installeren, geven ze ook een voorbeeldcode die je snel helpt om de library te gebruiken. Met deze voorbeeldcode heb ik ervoor kunnen zorgen dat de klant een bevestigingsmail krijgt. Hieronder is m.b.v. twee foto’s te zien hoe dit te werk gaat.

Klant maakt een reservering
Bevestigingsmail die de klant krijgt na het klikken op submit

Hieronder is de code te zien die ervoor zorgt dat de klant een bevestigingsmail krijgt waarin zijn/haar eigen informatie weer terug te zien is.

//mail_cust.php
<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

// Load Composer's autoloader
require 'vendor/autoload.php';

$mail = new PHPMailer(true);

try {
    //mail info
    $mail->setFrom('cristelshaircare@noreply.com', 'Cristel');
    $mail->addAddress($emailadres , $voornaam); //ontvanger
    $mail->addReplyTo('cristelshaircare@noreply.com', 'Cristel');

    //inhoud mail
    $mail->isHTML(true); //zorg dat het html is
    $mail->Subject = 'Bevestiging afspraak'; //onderwerp
    $mail->Body = '<h2>U heeft een afspraak ingepland.</h2>
                   <p>Beste '.$voornaam.',<br>
                   U heeft een afspraak ingepland voor '.$behandelingstype.'. U wordt op '.$datum.' verwacht om '.$tijd.'.<br>
                   Voor vragen kunt u bellen naar her volgende nummer: 06 52848034<br>
                   Tot dan!
                   </p>
                   <p>
                   Mvg,<br>
                   Cristel van der Vlies
                   </p>';

    //mail versturen
    $mail->send();

} catch (Exception $e) {
    echo "Mail kon niet worden verzonden. Bel de kapster voor meer info. Mailer Error: {$mail->ErrorInfo}";
}

Zoals je kan zien zorgt deze code in het begin ervoor dat hij phpmailer gebruikt d.m.v.

use PHPMailer\PHPMailer\PHPMailer; 
use PHPMailer\PHPMailer\Exception;

Vervolgens maak je de variabele $mail aan. Deze variabele gebruik je om een eigen mail op te zetten. Je kan nu bijvoorbeeld de verzender, ontvanger en het bericht aanpassen. Deze library zorgt ervoor dat je niet alles zelf hoeft te coderen. Op deze manier blijft het simpel en overzichtelijk.

Data

Je hebt een webapplicatie gebouwd op de server die gevoed wordt door een database. De database inhoud kan gelezen, bewerkt en verwijderd worden. Je hebt op de server een externe webservice aangesproken en hieruit data opgehaald.

Hieronder zijn de tabellen en de bijbehorende collommen te zien die ik gebruik voor mijn reserveringssysteem:

Ik heb met mijn opdrachtgever besproken dat ik alleen een reserveringssysteem maak. Deze komt met een reserveerpagina voor klanten om te reserveren (in dit geval index.php) en een adminagina waar de opdrachtgever zelf, de afspraken kan inzien (interface.php). Ik heb geprobeerd om het er goed uit te laten zien, maar ook voldoende functionaliteit toe te voegen zodat het reserveringssysteem toch bruikbaar is.

In het formulier dat je op index.php vul je de gevraagde gegevens in. Als deze correct worden ingevuld, word je doorverwezen naar een bevestigingspagina. Deze laat in het kort zien, voor wat en wanneer je hebt gereserveerd. Je krijgt meteen een bevestigingsmail. Vanuit hier kan je weer terug naar de hoofdpagina, wat in dit geval de reserveer pagina is. Hieronder is de code te zien die ervoor zorgt dat de reservering in de database wordt gezet:

//action.php
<?php
require_once "db.php";


$voornaam           = mysqli_escape_string($connect,$_POST['voornaam']);
$achternaam         = mysqli_escape_string($connect,$_POST['achternaam']);
$emailadres         = mysqli_escape_string($connect,$_POST['emailadres']);
$behandelingstype   = mysqli_escape_string($connect,$_POST['behandelingstype']);
$datum              = mysqli_escape_string($connect,$_POST['datum']);
$tijd               = mysqli_escape_string($connect,$_POST['tijd']);
$opmerking          = mysqli_escape_string($connect,$_POST['opmerking']);

$sql = "INSERT INTO reserveringen (voornaam, achternaam, emailadres, behandelingstype, datum, tijd, opmerking)
            VALUES ('$voornaam', '$achternaam', '$emailadres', '$behandelingstype', '$datum', '$tijd', '$opmerking')";


if (mysqli_query($connect, $sql)) {
    $id = mysqli_insert_id($connect);
    header( "location: confirm.php?id=$id");
} else {
    echo "Error:" . $sql . mysqli_error($connect);
};

require_once "includes/form-validation.php";
require_once "mail_cust.php";
?>
//form_validation.php
<?php
//Check if data is valid & generate error if not so
$errors = [];
if ($voornaam == "") {
    $errors['voornaam'] = 'First name cannot be empty'; //Alternative for errors behind input and not in summary
}
if ($achternaam == "") {
    $errors['achternaam'] = 'Last name cannot be empty';
}
if ($emailadres == "") {
    $errors['emailadres'] = 'Emailadress cannot be empty';
}
if ($behandelingstype == "") {
    $errors['behandelingstype'] = 'Behandelingstype cannot be empty';
}
if ($datum == "") {
    $errors['datum'] = 'Date cannot be empty';
}
if ($tijd == "") {
    $errors['tijd'] = 'Time cannot be empty';
}
?>

Deze blokken reageren zodra er op submit geklikt is. Als er iets niet ingevuld is geeft deze code een foutmelding. De informatie wordt pas doorgestuurd zodra alle velden zijn ingevuld. Dit gebeurd met de var $sql.

Om de reserveringen terug te zien heb ik een admin pagina gemaakt (interface.php). Hier kan de opdrachtgever zelf de reserveringen terug zien, verwijderen of veranderen. De code van deze pagina zal ik laten zien onder het kopje Beveiliging.
Als de opdrachtgever op edit klikt wordt ze doorverwezen naar een andere pagina waar alleen die speciefieke reservering staat (edit.php). Hier kan ze vervolgens de afspraak en datum/tijd van de afspraak veranderen.

//edit.php
<?php
require_once "db.php";

session_start();
if(!isset($_SESSION['name'])) {
    // redirect to login page
    header('Location: login.php');
    exit;
}

$id = $_GET['id'];

$query = "SELECT * FROM reserveringen WHERE id = '$id'";
$result = mysqli_query($connect, $query);
$row = mysqli_fetch_assoc($result);

$voornaam = mysqli_escape_string($connect, $row['voornaam']);
$achternaam = mysqli_escape_string($connect, $row['achternaam']);
$emailadres = mysqli_escape_string($connect, $row['emailadres']);
$behandelingstype = mysqli_escape_string($connect, $row['behandelingstype']);
$datum = mysqli_escape_string($connect, $row['datum']);
$tijd = mysqli_escape_string($connect, $row['tijd']);
$opmerking = mysqli_escape_string($connect, $row['opmerking']);
?>

Hierboven is de code te zien van edit.php. Allereerst checkt de code of je nog ingelogd bent d.m.v. een session. Als dit niet het geval is, wordt je meteen doorverwezen naar de login.php. Vervolgens maak ik een variabele aan van de id met de GET methode. De opgevraagde data toon ik in een tabel die blijft herhalen tot er geen informatie meer op te halen is. Vervolgens maak ik weer van alle informatie, variabelen die ik later tussen de html code gebruik.
Zodra je op submit klikt activeer je de volgende code:

//admin_edit.php
<?php
require_once "db.php";

$id = $_POST['id'];
$edit_voornaam = $_POST['edit_voornaam'];
$edit_achternaam = $_POST['edit_achternaam'];
$edit_emailadres = $_POST['edit_emailadres'];
$edit_behandelingstype = $_POST['edit_behandelingstype'];
$edit_datum = $_POST['edit_datum'];
$edit_tijd = $_POST['edit_tijd'];
$edit_opmerking = $_POST['edit_opmerking'];


$sql = "UPDATE reserveringen
        SET behandelingstype = '$edit_behandelingstype', datum = '$edit_datum', tijd = '$edit_tijd'
        WHERE id = '$id'";

if (mysqli_query($connect, $sql)){
    header("location: interface.php");
}
else {
    echo 'Er ging iets fout in de database' . $sql . mysqli_error($connect);
}

mysqli_close($connect);
?>

Deze code zorgt ervoor dat de aangepast data veranderd wordt in de database m.b.v. de UPDATE functie. Als er op submit geklikt is, veranderd de data in de database naar de nieuwe ingevulde data, als die er is.

In de interface heeft de opdrachtgever ook de optie om afspraken te verwijderen. Dit kan je doen door op delete te klikken naast de afspraak die je verwijderd wilt hebben.

//delete.php
<?php
require_once "db.php";

$id = $_GET['id'];

$sql = "DELETE FROM reserveringen WHERE id = '$id'";

if (mysqli_query($connect, $sql)){
    header("location: interface.php");
}
else {
    echo "Kon niet verwijderen" . $sql . mysqli_error($connect);
}

mysqli_close($connect);

?>

In de code hierboven kan je zien dat de afspraak wordt herkend door de id. Deze id wordt gebruikt om in de DELETE functie de afspraak op te zoeken en te verwijderen. Als de afspraak verwijderd is word je meteen terug verwezen naar interface.php.

Beveiliging

Een deel van je website is niet toegankelijk zonder in te loggen. Je form invoer wordt op de server gevalideerd en is beveiligd tegen xss en sql injecties. Wachtwoorden worden veilig opgeslagen.

Zoals ik in het vorige punt heb verteld, heb in een adminpagina (interface.php) gemaakt, die alleen de admin kan bezoeken door in te loggen. Ik heb één account aangemaakt via de database, aangezien mijn opdrachtgever alleen werkt. Ze is ook niet van plan om werknemers in dienst te nemen aangezien ze thuis een salon heeft. Dit account heb ik in mijn database aangemaakt en handmatig via php een wachtwoord gehasht. Dit heb ik gedaan met de volgende code:

password_hash(‘wachtwoord’,PASSWORD_DEFAULT);

Uiteindelijk ziet het er zo uit in mijn database

Hieronder is de php code te zien die ik heb geschreven om in te loggen.

//login.php
<?php
require_once "db.php";

//On post submit, check the credentials
if (isset($_POST['submit'])) {

    //Retrieve values
    $name = mysqli_escape_string($connect, $_POST['name']);
    $password = mysqli_escape_string($connect, $_POST['password']);

    //Get password & name from DB
    $query = "SELECT name, password FROM users WHERE name = '$name'";
    $result = mysqli_query($connect, $query);
    $user = mysqli_fetch_assoc($result);

    //Go on if we got an user
    if ($user) {
        //Validate password
        if (password_verify($password, $user['password'])) {
            //Set session variable, redirect & exit script
            $_SESSION['name'] = $user['name'];
            header('Location: interface.php');
            exit;
        } else {
            $message = "Inloggegevens komen niet overeen.";
        }
    } else {
        $message = "Inloggegevens komen niet overeen.";
    }
}
?>

In deze code wordt de ingevulde gegevens d.m.v.

(password_verify($password, $user['password']))

vergeleken met de inloggegevens die op de server staan. Als deze overeen komen, wordt de opdrachtgever doorgestuurd naar interface.php. Als deze niet kloppen krijg je een foutmelding waarin staat dat de inloggegevens niet overeen komen. Ik heb er bewust voor gekozen om niet te zeggen wat fout is. Als je dit weet als onbevoegde, is het makkelijker om binnen te komen.

De inlogpagina is net als het reserveringsformulier, beveiligd tegen sql en xss injections. Dit doe ik door gebruik te maken van mysqli_escape_string(). Dit zorgt ervoor dat de ingevulde data omgezet wordt naar een string. Als dit gebeurd kan er geen code naar de database gestuurd worden. Ik heb dit getest door een simpele alert() te gebruiken. Dit is een functie die normaal gesproken een alert geeft op de website. Omdat deze hiertegen beschermd is werkt hij niet.

De funtie htmlentities() heb ik gebruikt op het moment dat ik de data ophaal en laat zien op interface.php. Door htmlentities() kan de opgehaalde data geen javascript uitvoeren.

<td><?= htmlentities($row['id'])?></td>
<td><?= htmlentities($row['voornaam'])?></td>
<td><?= htmlentities($row['achternaam'])?></td>
<td><?= htmlentities($row['emailadres'])?></td>
<td><?= htmlentities($row['behandelingstype'])?></td>
<td><?= htmlentities($row['datum'])?></td>
<td><?= htmlentities($row['tijd'])?></td>
<td><?= htmlentities($row['opmerking'])?></td>
<td><a href="edit.php?id=<?= $row['id']?>">Edit</a></td>
<td><a href="delete.php?id=<?= $row['id']?>">Delete</a></td>