We maken een contactformulier met Bootstrap. De invoer wordt server-side gevalideerd en veilig bewaard in MariaDB via PDO prepared statements.
htdocs/project/ bij XAMPP/MAMP/WAMP) of start lokaal: php -S localhost:8000 in de project/ map.http://localhost/… (niet via 127.0.0.1:5500).Voer dit SQL-script éénmalig uit (via phpMyAdmin of CLI):
CREATE DATABASE IF NOT EXISTS projectdb
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE projectdb;
CREATE TABLE IF NOT EXISTS contact_messages (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Maak config.php in je project (buiten assets/):
<?php
// config.php — eenvoudige PDO-connector
$DB_HOST = 'localhost';
$DB_NAME = 'projectdb';
$DB_USER = 'root'; // XAMPP/MAMP default
$DB_PASS = ''; // vaak leeg op XAMPP; pas aan indien nodig
$dsn = "mysql:host=$DB_HOST;dbname=$DB_NAME;charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $DB_USER, $DB_PASS, $options);
} catch (PDOException $e) {
exit('DB-verbinding mislukt: ' . htmlspecialchars($e->getMessage()));
}
config.php later in includes/ en sluit ‘m uit in Git (.gitignore).
Maak contact.php. Bovenaan staat PHP die POST verwerkt; daaronder de HTML met Bootstrap.
<?php
require __DIR__ . '/config.php';
$errors = [];
$success = false;
// Bij POST: valideren en opslaan
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Trim input
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
// Validatie
if ($name === '' || mb_strlen($name) < 2) {
$errors['name'] = 'Naam is verplicht (min. 2 tekens).';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Geef een geldig e-mailadres op.';
}
if ($message === '' || mb_strlen($message) < 10) {
$errors['message'] = 'Schrijf een korte boodschap (min. 10 tekens).';
}
// Opslaan indien geldig
if (!$errors) {
$stmt = $pdo->prepare(
'INSERT INTO contact_messages (name, email, message) VALUES (?, ?, ?)'
);
$stmt->execute([$name, $email, $message]);
$success = true;
// Form velden leegmaken na succes
$name = $email = $message = '';
}
}
// Helper voor repopuleren
function e($s){ return htmlspecialchars($s ?? '', ENT_QUOTES, 'UTF-8'); }
?>
<!doctype html>
<html lang="nl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contact</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary fixed-top" id="site-navbar">...</nav>
<main id="main-content" class="container" style="margin-top:5rem">
<h1 class="pt-3">Contact</h1>
<?php if ($success): ?>
<div class="alert alert-success">Bedankt! Je bericht werd verzonden.</div>
<?php endif; ?>
<form method="post" novalidate class="row g-3">
<div class="col-md-6">
<label for="name" class="form-label">Naam</label>
<input type="text" class="form-control <?= isset($errors['name']) ? 'is-invalid' : '' ?>" id="name" name="name" value="<?= e($name ?? '') ?>" required>
<div class="invalid-feedback"><?= $errors['name'] ?? '' ?></div>
</div>
<div class="col-md-6">
<label for="email" class="form-label">E-mail</label>
<input type="email" class="form-control <?= isset($errors['email']) ? 'is-invalid' : '' ?>" id="email" name="email" value="<?= e($email ?? '') ?>" required>
<div class="invalid-feedback"><?= $errors['email'] ?? '' ?></div>
</div>
<div class="col-12">
<label for="message" class="form-label">Boodschap</label>
<textarea class="form-control <?= isset($errors['message']) ? 'is-invalid' : '' ?>" id="message" name="message" rows="5" required><?= e($message ?? '') ?></textarea>
<div class="invalid-feedback"><?= $errors['message'] ?? '' ?></div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Verzenden</button>
</div>
</form>
<hr class="my-4">
<h2 class="h5">Ingekomen berichten (laatste 5)</h2>
<?php
$rows = $pdo->query('SELECT name, email, message, created_at FROM contact_messages ORDER BY id DESC LIMIT 5')->fetchAll();
if ($rows):
?>
<div class="list-group mb-5">
<?php foreach($rows as $r): ?>
<div class="list-group-item">
<div class="d-flex justify-content-between">
<strong><?= e($r['name']) ?></strong>
<small class="text-muted"><?= e($r['created_at']) ?></small>
</div>
<div class="small text-muted"><?= e($r['email']) ?></div>
<p class="mb-0"><?= nl2br(e($r['message'])) ?></p>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="text-muted">Nog geen berichten.</p>
<?php endif; ?>
</main>
<footer class="site-footer bg-dark text-light mt-5" id="site-footer">...</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
/contact.php via http://localhost/….projectdb en tabel contact_messages bestaan.config.php werkt (PDO met UTF-8 en exceptions).