E2 - Sample Solution
Tags: php, tutorial, sql
Published: 2020-04-14 18:48:30

Files in example:
* [index.php](#index)
* [process_my_form.php](#process-my-form)
* [on_success.php](#on-success)

## index.php <a name="index"></a>
```php
<?php
/** Load an array from a cookie and clear the cookie. */
function loadAndClearArrayFromCookie($name)
{
    if (isset($_COOKIE[$name]) && !empty($_COOKIE[$name])) {
        $array = json_decode($_COOKIE[$name], true);
        // Reset the cookies by expiring them.
        setcookie($name, "", time() - 1000, "/");
        return $array;
    }
    // Return an empty array if cookie not found.
    return [];
}


$formErrors = loadAndClearArrayFromCookie("formErrors");
$lastInput = loadAndClearArrayFromCookie("lastInput");


?>
<html>
<head>
    <style>
        body {
            height: 100vh;
            background-color: #ff8000;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        label, input, span.error, form > button {
            display: block;
            font-family: "Helvetica";
        }
        label, input, form > button {
            color: #773d04;
        }
        input {
            padding: 0.3em 1em;
            margin: 12px 0;
        }
        span.error {
            font-size: 0.85em;
            color: #e42512;
            text-shadow: 1px 1px #ff6f6f;
        }
        input, span.error {
            margin-left: 10px;
        }
        form {
            margin-top: 100px;
            width: 300px;
            padding: 50px;
            /* see: https://neumorphism.io/#ff8000 */
            border-radius: 50px;
            background: #ff8000;
            box-shadow: inset 20px 20px 16px #de6f00, 
            inset -20px -20px 16px #ff9100;
        }
        form > div {
            margin-bottom: 20px;
            padding: 20px;
            border-radius: 28px;
            background: linear-gradient(145deg, #ff8900, #e67300);
            box-shadow:  13px 13px 21px #de6f00, 
             -13px -13px 21px #ff9100;
        }
        form > button {
            margin-top: 50px;
            border:none;
            padding: 10px;
            width: 75px;
            border-radius: 62px;
            background: linear-gradient(145deg, #e67300, #ff8900);
            box-shadow:  7px 7px 14px #d96d00, 
             -7px -7px 14px #ff9300;
        }
        form > button:hover {
            border-radius: 62px;
            background: linear-gradient(145deg, #e67300, #ff8900);
            box-shadow:  7px 7px 14px #d96d00, 
             -7px -7px 14px #ff9300;
        }
        form > button:active {
            border-radius: 62px;
            background: #ff8000;
            box-shadow: inset 13px 13px 26px #e87400, 
            inset -13px -13px 26px #ff8c00;
        }


        input {
            border: none;
            border-radius: 62px;
            background: #ff8000;
            box-shadow: inset 13px 13px 26px #e87400, 
            inset -13px -13px 26px #ff8c00;
        }
    </style>
</head>
<body><form action="process_my_form.php" method="post">
    <div> <!--  First name field -->
        <label>First Name</label>
        <input name="first_name" value="<?=$lastInput["first_name"] ?? "";?>">
        <span class="error"><?=$formErrors["first_name"] ?? "";?></span>
    </div>
    <div> <!--  Last name field -->
        <label>Last Name</label>
        <input name="last_name" value="<?=$lastInput["last_name"] ?? "";?>">
        <span class="error"><?=$formErrors["last_name"] ?? "";?></span>
    </div>
    <button>Submit</button>
</form></body></html>
```

## process_my_form.php <a name="process-my-form"></a>
```php
<?php


define("ERROR_TOO_LONG", "Must be shorter than ");
define("ERROR_TOO_SHORT", "Must be longer than ");
define("ERROR_EMPTY", "Must not be empty");


/** Returns the input with potentially dangerous parts removed. */
function sanitize(string $input, mysqli $databaseLink): string
{
    $input = strip_tags($input); // Remove HTML tags, preventing abuse
    $input = $databaseLink->real_escape_string($input); // Prevent SQL injections
    return $input;
}


/** Returns whether the input is empty or not. */
function isPresent(string $input): bool
{
    return !empty($input);
}


/** Returns whether the input is longer that maxLength. */
function isLongerThan(string $input, int $maxLength): bool
{
    return strlen($input) > $maxLength;
}


/** Returns whether the input is shorter than minLength. */
function isShorterThan(string $input, int $minLength): bool
{
    return strlen($input) < $minLength;
}


/**
 * Process the registration form.
 *
 * @param array $inputArray Either $_GET or $_POST, depending on what
 * the form method was.
 */
function processRegisterForm(array $inputArray)
{
    $databaseLink = new mysqli("localhost", "root", "", "NeatTreats");
    $firstName = sanitize($inputArray["first_name"], $databaseLink);
    $lastName = sanitize($inputArray["last_name"], $databaseLink);
    $databaseLink->close();


    $formErrors = [];
    if (isPresent($firstName)) { // optional field - only check if specified
        if (isLongerThan($firstName, 20)) { // length check
            $formErrors["first_name"] = ERROR_TOO_LONG . "20";
            // error message will specify it was longer than 20
        }
    }
    if (!isPresent($lastName)) { // presence check
        $formErrors["last_name"] = ERROR_EMPTY;
    }


    $addedSuccessfully = false;
    if (empty($formErrors)) {
        $databaseLink = new mysqli("localhost", "root", "", "NeatTreats");
        $databaseLink->query(
            "INSERT INTO Customer(FirstName, LastName)" .
            "VALUES ($firstName, $lastName);"
        );
        // No error means added succesfully!
        if (empty($databaseLink->error)) $addedSuccessfully = true;
        $databaseLink->close(); // Always remember to close the database.
    }


    if ($addedSuccessfully) {
        /* I have provided 3 methods of automatic redirection below.
        Also provide a link just in case the automatic redirection
        fails. */
        echo "<p>You were added to our database!</p>";
        echo "<script>window.location='on_success.php';</script>"; // Javascript redirection
        // header("Location: on_success.php"); // Header redirection
        // echo "<meta http-equiv='refresh' content='0;url=on_success.php'>"; // HTML redirection
        echo "<a href='on_success.php'>Continue</a>";
    } else {
        // Redirect back to form page.
        echo "<p>Could not add record due to invalid input</p>";
        echo "<script>window.location='index.php';</script>";
        echo "<a href='index.php'>Try again</a>";


        /* Set form errors and last inputs by a cookie.
        json_encode is so the cookie sent is a string. It should be
        decoded at the other end.
        time() + 3600 makes the cookie expire in 3600 seconds (1 hour)
        from now.
        Set the cookie path to "/" so that it can be accessed from
        the form on the other page. */
        setcookie("formErrors", json_encode($formErrors), time() + 3600, "/");
        setcookie("lastInput", json_encode($inputArray), time() + 3600, "/");
    }
}
?>


<html><body><?php processRegisterForm($_POST); ?></body></html>
```

## on_success.php <a name="on-success"></a>
```php
<html><body>
    <p>Well done, you're in our database!</p>
</body></html>
```

Parent topic: [Example 2](https://dev.to/herobank110/example-2-saving-data-from-a-form-4g33)