Skip to content

Lab 1: Form Handling & Validation

In this lab, you will build a Product Feedback Form using vanilla PHP (no framework). You will create an HTML form that submits data via POST to a separate processing script, validate all inputs on the server side, and use the Post-Redirect-Get (PRG) pattern to prevent duplicate submissions. After successful processing, a flash message stored in $_SESSION will communicate the result back to the user.


By completing this lab, you will:

  • Create reusable layout includes (header.php, footer.php) and include them with require.
  • Build an HTML form that submits data via POST to a separate processing script.
  • Retrieve and sanitize user input using filter_input() and trim().
  • Implement server-side validation with an $errors array and display error messages.
  • Build a sticky form that preserves user input when validation fails.
  • Apply the Post-Redirect-Get (PRG) pattern to prevent duplicate form submissions.
  • Use $_SESSION to store and display flash messages after a redirect.
  • Escape output with htmlspecialchars() to prevent XSS.

Before starting this lab, ensure you have:

  • A local PHP development environment (e.g., XAMPP or WAMP).
  • Basic understanding of HTML forms and PHP syntax.
  • Familiarity with PHP sessions (session_start(), $_SESSION).

Create the following folder and file structure inside your project directory:

project/
├── includes/
│ ├── header.php
│ └── footer.php
├── feedback.php
└── process-feedback.php

Objective: Create reusable layout files that will be included in every page.

  1. Create an includes/ folder in your project directory.
  2. Inside includes/, create two files: header.php and footer.php.
  3. Write the code for each file based on the requirements below.
FileMust Include
header.phpThe HTML5 doctype, a <head> section with Bootstrap 5 CSS and JS linked from CDN (see the Bootstrap Getting Started ↗ page for the CDN links), an opening <body> tag, and an opening <div> with the Bootstrap container mt-4 classes. Use a $pageTitle variable for the <title> tag content.
footer.phpThe closing </div> for the container, and the closing </body> and </html> tags.

Objective: Create feedback.php, the page that displays the feedback form, shows flash messages after a redirect, and redisplays validation errors with preserved input.

Create a file named feedback.php in your project root. This file must handle the following responsibilities in order:

  1. Start the session at the very top of the file (before any HTML output).
  2. Check for a flash message in $_SESSION['flash_message']. If one exists, store it in a local variable, then unset() it from the session.
  3. Check for validation errors in $_SESSION['errors']. If they exist, store them in a local variable, then unset() them.
  4. Retrieve sticky form data from $_SESSION['form_data'] (if present), store it in a local variable, then unset() it.
  5. Set $pageTitle and include includes/header.php.
  6. Display the flash message (if one was retrieved) inside a Bootstrap alert alert-success div.
  7. Display validation errors (if any were retrieved) inside a Bootstrap alert alert-danger div. You can either show them as a list or as individual alerts.
  8. Build the HTML form with the specifications below.
  9. Include includes/footer.php.

Your form must use method="POST" and action="process-feedback.php". It should contain the following fields styled with Bootstrap form classes:

FieldTypename AttributeNotes
Product NameText inputproduct_nameRequired. Preserve the submitted value when redisplaying the form after a validation error.
RatingSelect dropdownratingOptions: 1 through 5. Include a disabled default option with the text “Choose a rating”. Preserve the selected value after a validation error.
EmailEmail inputemailRequired. Preserve the submitted value after a validation error.
CommentsTextareacommentsRequired. Preserve the submitted value between the opening and closing textarea tags after a validation error.

Add a Submit button with Bootstrap’s btn btn-primary classes.


Objective: Create process-feedback.php, the script that receives the form data, validates it, and redirects back to the form page with either errors or a success message.

Create a file named process-feedback.php in your project root. This file must do the following:

  1. Start the session at the top.
  2. Guard against non-POST requests: check $_SERVER['REQUEST_METHOD']. If it is not POST, redirect to feedback.php and stop execution.
  3. Retrieve all four inputs using filter_input() and trim().
  4. Initialize an empty $errors array.
  5. Validate each field according to the rules in the table below. For every failed rule, add an appropriate error message string to the $errors array.
  6. If errors exist:
    • Store the $errors array in $_SESSION['errors'].
    • Store the submitted form data in $_SESSION['form_data'] as an associative array (so the form page can repopulate the fields).
    • Redirect to feedback.php and stop execution.
  7. If no errors:
    • Store a success message (e.g., “Thank you! Your feedback has been submitted.”) in $_SESSION['flash_message'].
    • Redirect to feedback.php and stop execution.
FieldRule(s)
Product NameMust not be empty.
RatingMust be a valid integer between 1 and 5. Use filter_input() with FILTER_VALIDATE_INT to retrieve and validate in one step.
EmailMust not be empty. If not empty, must be a valid email format. Use filter_var() with FILTER_VALIDATE_EMAIL for format validation.
CommentsMust not be empty.

Now that you have built both files, let’s trace the full request cycle to understand how the Post-Redirect-Get pattern works.

  1. The user fills out the form on feedback.php and clicks Submit.
  2. The browser sends a POST request to process-feedback.php.
  3. The server validates the input. All fields are valid.
  4. The server stores a success message in $_SESSION['flash_message'].
  5. The server responds with a redirect (Location: feedback.php).
  6. The browser follows the redirect and sends a GET request to feedback.php.
  7. feedback.php reads $_SESSION['flash_message'], displays it, and unsets it.
  8. If the user refreshes the page, only the GET request repeats. No duplicate POST.
  1. The user submits the form with invalid data.
  2. The browser sends a POST request to process-feedback.php.
  3. The server validates the input and finds errors.
  4. The server stores $errors and the submitted form data in $_SESSION.
  5. The server responds with a redirect back to feedback.php.
  6. The browser follows the redirect (GET).
  7. feedback.php reads the errors and form data from the session, displays the errors, repopulates the form fields, and unsets both session keys.

Open feedback.php in your browser and run through the following test scenarios.

  • Empty submission: Submit the form with all fields empty. Four validation error messages should appear. No crash or blank page.
  • Partial input with invalid email: Fill in only the product name and enter an invalid email (e.g., “notanemail”). Submit. Errors should appear for rating, email format, and comments. The product name and the invalid email should still be in their fields (sticky form).
  • Valid submission: Fill in all fields correctly and submit. A green success message should appear. The form fields should be cleared.
  • Refresh after success: After seeing the success message, refresh the page. The success message should not reappear, and the browser should not warn about resubmitting form data.
  • Direct GET access: Type process-feedback.php directly in the browser address bar. You should be redirected to feedback.php with no errors displayed.