Capstone Project

Course 1 · Capstone
Capstone Project: A Multi-File Profile Card Generator
Bringing together variables, control flow, functions, arrays, strings, forms, and includes into one small real project

This final chapter doesn't introduce new syntax — it's a small, complete project that uses every concept from Chapters 1 through 9 together, the way a real (if simple) PHP page actually gets built: split across files, validating form input, and formatting output.

What We're Building

A "Profile Card Generator" — a form where a visitor enters their name, age, and favourite colour. On submission, the page validates the input and displays a neatly formatted profile card, reusing a shared header/footer and a small library of helper functions.

Ch 2
Variables & types
Ch 3
if/else validation
Ch 4
foreach over errors
Ch 5
Functions & return values
Ch 6
Arrays of errors
Ch 7
trim, ucwords, sprintf
Ch 8
$_POST, $_SERVER
Ch 9
require_once, include

Project Structure

profile-card/ functions.php — validation + formatting helpers header.php — shared page header footer.php — shared page footer index.php — the form + result page

functions.php — The Helper Library

functions.php
<?php function validateProfile($name, $age, $colour) { $errors = []; if (trim($name) === '') { $errors[] = "Name is required."; } if (!is_numeric($age) || $age < 0 || $age > 130) { $errors[] = "Please enter a valid age between 0 and 130."; } if (trim($colour) === '') { $errors[] = "Favourite colour is required."; } return $errors; // empty array means "no errors" } function formatProfileCard($name, $age, $colour) { $cleanName = ucwords(trim($name)); $cleanColour = strtolower(trim($colour)); return sprintf("%s is %d years old and loves the colour %s.", $cleanName, (int)$age, $cleanColour); } ?>

Two pure functions: one returns an array of validation problems (Chapter 6's arrays + Chapter 3's conditions), the other builds the final display string (Chapter 7's string functions). Neither echoes anything directly — they hand results back via return (Chapter 5), which keeps them reusable and easy to test independently of any HTML.

header.php and footer.php

header.php
<header style="font-family:sans-serif"> <h2>Profile Card Generator</h2> </header>
footer.php
<footer> <p><small>PHP Fundamentals Capstone</small></p> </footer>

index.php — Tying It All Together

index.php
<?php require_once __DIR__ . '/functions.php'; $errors = []; $card = null; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $name = $_POST['name'] ?? ''; $age = $_POST['age'] ?? ''; $colour = $_POST['colour'] ?? ''; $errors = validateProfile($name, $age, $colour); if (count($errors) === 0) { $card = formatProfileCard($name, $age, $colour); } } require __DIR__ . '/header.php'; ?> <form method="post"> <input name="name" placeholder="Name"> <input name="age" placeholder="Age"> <input name="colour" placeholder="Favourite colour"> <input type="submit"> </form> <?php if (!empty($errors)): ?> <ul> <?php foreach ($errors as $error): ?> <li><?= $error ?></li> <?php endforeach; ?> </ul> <?php elseif ($card): ?> <p><?= $card ?></p> <?php endif; ?> <?php include __DIR__ . '/footer.php'; ?>

Notice every chapter's skill at work: $_SERVER/$_POST (Ch 8) drive the logic, ?? (Ch 3) guards against missing keys, the validation function returns an array (Ch 6) of problems, a foreach (Ch 4) displays them, and require/include (Ch 9) bring in the shared header/footer — with require chosen for the header (essential layout) and include for the footer (less critical), matching Chapter 9's guidance.

Still not production-safe — output isn't escaped with htmlspecialchars()
Exactly as flagged in Chapter 8, this capstone echoes user-supplied values without sanitising them, which is fine for learning but not appropriate for a real public-facing page. Output escaping is covered properly in the Intermediate course, alongside more thorough validation.

Coding Challenge — Extend the Capstone

Final Challenge

Add a fourth field to the form: "hobbies", expecting a comma-separated list (e.g. "reading, chess, hiking"). In functions.php, write a new function that uses explode() and array_map() with trim() to turn it into a clean array, then use implode() to redisplay it as a tidy bulleted-feeling sentence in the profile card (e.g. "Hobbies: reading, chess, and hiking."). Wire it into index.php alongside the existing fields.

📄 View solution

Course 1 Complete — PHP Fundamentals

  • Chapters 1-9 covered: tags/echo, variables & types, operators & control flow, loops, functions & scope, arrays, strings, superglobals/forms, and includes
  • This capstone combined all nine into one small, genuinely structured multi-file project
  • Known, deliberate gap: no output escaping (htmlspecialchars) or database persistence yet — both covered in later courses
  • Next: PHP Intermediate (Course 2) — object-oriented PHP, sessions, file handling, error handling, and database basics