Server-side Defense: PHP Validation, Hashing, And MariaDB Storage

PHP Secure Forms 101
PHP Secure Forms 101

Live stream set for 2025-11-05 at 14:00:00 Eastern

Ask questions in the live chat about any programming or lifestyle topic.

This livestream will be on YouTube or you can watch below.

PHP Validation, Santization, and Storage

Every developer knows the challenge: you need to collect user data via a form, and that data must be both valid and securely stored.

In the browser, you can use powerful HTML5 Regular Expressions for instant user feedback (If you missed that, see: HTML5 Regular Expressions).

But here is the most important truth in web security: You must never trust client-side validation.

Any user can bypass client-side checks with ease. The real defense happens on the server. This guide shows you how to build a robust PHP endpoint that handles the process, from re-validating the data to securely storing it in a MariaDB database and notifying the administrator.

1. The Goal: Strict Input Rules

We are building the PHP backend for a registration form that enforces these rules:

Field Client-Side Rule (HTML5 Regex) Server-Side Enforcement (PHP)
Username 4-16 lowercase letters/numbers preg_match()
Password Min 8 chars, must include upper, lower, and number password_hash()

2. The Database Blueprint: Creating the Users Table

Our PHP script connects to MariaDB (or MySQL) and ensures the necessary users table exists. We use CREATE TABLE IF NOT EXISTS to ensure the script works even on a fresh setup.

-- SQL executed by the PHP script to ensure the table is ready
CREATE TABLE IF NOT EXISTS users (
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(16) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL, -- Long field for secure hash
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

3. The Secure PHP Backend Code (process_form.php)

This script contains the entire logic: input handling, security checks, database communication, and admin email notification. Remember to update the configuration variables (lines 3-6) before testing!

// --- 1. CONFIGURATION SECTION (CRITICAL: UPDATE THESE VALUES) ---
$servername = "localhost";
$db_username = "your_db_user";     // Your MariaDB/MySQL Username
$db_password = "your_db_password"; // Your MariaDB/MySQL Password
$dbname = "user_db";            // The name of your database (MUST EXIST)
$admin_email_recipient = "admin@yourwebsite.com"; // For new user notification

// Initialize error and success variables
$usernameError = '';
$passwordError = '';
$response = ['success' => false, 'message' => ''];

if ($_SERVER["REQUEST_METHOD"] == "POST") {

    // Retrieve and trim inputs
    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? ''; 
    
    // --- 2. Validation Checks (Matching your form rules) ---
    // Validate Username (4-16 lowercase letters/numbers)
    if (empty($username)) {
        $usernameError = "Username is required.";
    } elseif (strlen($username) < 4 || strlen(trim($username)) > 16) {
        $usernameError = "Username must be between 4 and 16 characters.";
    } elseif (!preg_match("/^[a-z0-9]+$/", $username)) {
        $usernameError = "Username must contain only lowercase letters and numbers.";
    }

    // Validate Password (Min 8 chars, incl. upper, lower, and number)
    if (empty($password)) {
        $passwordError = "Password is required.";
    } elseif (strlen($password) < 8) {
        $passwordError = "Password must be at least 8 characters long.";
    } elseif (!preg_match("/&#91;A-Z&#93;/", $password) || !preg_match("/&#91;a-z&#93;/", $password) || !preg_match("/&#91;0-9&#93;/", $password)) {
        $passwordError = "Password must include at least one uppercase letter, one lowercase letter, and one number.";
    }

    // --- 3. Database Connection and Preparation ---
    if (empty($usernameError) && empty($passwordError)) {

        $conn = new mysqli($servername, $db_username, $db_password, $dbname);

        if ($conn->connect_error) {
            $response['message'] = "❌ Server Error: Database connection failed. Check credentials/server.";
        } else {
            
            // **DATABASE PREP: CREATE TABLE IF NOT EXISTS**
            $table_sql = "
                CREATE TABLE IF NOT EXISTS users (
                    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                    username VARCHAR(16) NOT NULL UNIQUE,
                    password_hash VARCHAR(255) NOT NULL,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )";

            if ($conn->query($table_sql) === FALSE) {
                error_log("MariaDB Table Creation Error: " . $conn->error);
            }
            
            // --- 4. User Registration and Data Storage ---
            $hashed_password = password_hash($password, PASSWORD_DEFAULT);
            $sql = "INSERT INTO users (username, password_hash) VALUES (?, ?)";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param("ss", $username, $hashed_password);

            if ($stmt->execute()) {
                $response['success'] = true;
                $response['message'] = " Success! User registered and stored securely.";
                
                // --- 5. Admin Notification ---
                $subject = "NEW User Registration Alert";
                $message_body = "A new user has registered:\nUsername: " . $username . "\nTime: " . date("Y-m-d H:i:s");
                $headers = "From: webmaster@yourdomain.com\r\n";
                
                if (!mail($admin_email_recipient, $subject, $message_body, $headers)) {
                    error_log("Failed to send admin email for user: " . $username);
                }

            } else {
                if ($conn->errno === 1062) {
                    $response['message'] = "❌ Username '{$username}' is already taken. Please choose another.";
                } else {
                    $response['message'] = "❌ Database error during registration.";
                    error_log("MariaDB Error: " . $stmt->error);
                }
            }

            $stmt->close();
            $conn->close();
        }
    } else {
        $errors = array_filter([$usernameError, $passwordError]);
        $response['message'] = "Validation Failed: " . implode(' ', $errors);
    }
} else {
    $response['message'] = "Invalid request method.";
}

// Simple redirect on success or show error
if ($response['success']) {
    header("Location: success_page.html"); 
    exit();
} else {
    echo "<h1>Registration Status</h1>";
    echo "<p style='color: red;'>" . $response['message'] . "</p>";
}

4. Security Deep Dive: Three Critical Steps

The value of this PHP endpoint is in its security implementation, making it a professional-grade handler.

A. Reinforcing Validation with preg_match

PHP re-validates the input using preg_match() to enforce the length and character rules. This catch-all validation prevents improperly formatted data from ever reaching your database or crashing your application.

B. Password Hashing (The Non-Negotiable Step)

The line $hashed_password = password_hash($password, PASSWORD_DEFAULT); is the most important security measure here.

  • NEVER store a raw password! password_hash() converts the user’s password into an irreversible hash. If an attacker breaches your database, they only get the hash, not the actual password.
  • Verification: Later, when a user logs in, you use the PHP function password_verify() to check the raw password against the stored hash.

C. Preventing SQL Injection with Prepared Statements

The mysqli::prepare() and bind_param() methods are essential. They separate the SQL command from the user-provided data (? placeholders). This guarantees that malicious code entered into the form cannot be executed against your database.

Screenshots and Screencast

An HTML5 Regex Form Submit Error
Web Browser Displaying An HTML5 Regular Expression Form Submission Error

An HTML5 Regex Form Submission
Web Browser Displaying An HTML5 Regular Expression Submission Message

Form SubmissionIn Database
Web Browser Displaying PHPMyAdmin Showing Database Table Results

HTML Drag And Drop Upload Animation Video

Further Learning and Support

If you’re excited by the power of connecting HTML forms to a secure database, you’re ready to dive deeper into PHP.

I offer comprehensive resources to help you master these essential web development skills:

I am also available for one-on-one programming tutorials and services for updating or migrating existing PHP applications to modern, secure standards.

Recommended Resources:

Disclosure: Some of the links above are referral (affiliate) links. I may earn a commission if you purchase through them - at no extra cost to you.

About Edward

Edward is a software engineer, web developer, and author dedicated to helping people achieve their personal and professional goals through actionable advice and real-world tools.

As the author of impactful books including Learning JavaScript, Learning Python, Learning PHP, Mastering Blender Python API, and fiction The Algorithmic Serpent, Edward writes with a focus on personal growth, entrepreneurship, and practical success strategies. His work is designed to guide, motivate, and empower.

In addition to writing, Edward offers professional "full-stack development," "database design," "1-on-1 tutoring," "consulting sessions,", tailored to help you take the next step. Whether you are launching a business, developing a brand, or leveling up your mindset, Edward will be there to support you.

Edward also offers online courses designed to deepen your learning and accelerate your progress. Explore the programming on languages like JavaScript, Python and PHP to find the perfect fit for your journey.

📚 Explore His Books – Visit the Book Shop to grab your copies today.
💼 Need Support? – Learn more about Services and the ways to benefit from his expertise.
🎓 Ready to Learn? – Check out his Online Courses to turn your ideas into results.

Leave a Reply

Your email address will not be published. Required fields are marked *