You are still not using an array for the errors. The current code will only show one error at a time. By using an array to hold the user/validation errors, you can validate all the inputs at once, so that the user can see and fix all of the validation problems at once, without needing to resubmit the form after correcting each one.
At the point of displaying the form, you can test if the array holding the user/validation errors is not empty(), then either loop over the array or implode() it to display the errors.
Here are some additional points -
- You should have separate first and last name fields/columns, so that you can distinguish between names like Ross Martin and Martin Ross.
- Don’t change the name or capitalization of any particular piece of data. This is just creating more work for you keeping track of the different variations. Use the same name for any piece of data throughout the code/query.
- Time() values are not unique and are easy to guess/generate. You should use random_bytes() for the token generator.
Here’s example code showing the points given and how to test in the database exception catch block for a duplicate index error -
// initialization
session_start();
$data = []; // array to hold a trimmed working copy of the form data. will also receive the initial data when editing/updating existing data
$errors = []; // array to hold user/validation errors
// post method form processing
if($_SERVER['REQUEST_METHOD'] == "POST")
{
// php has a large number of array functions that will do work for you, when operating on sets (arrays) of data
// you can trim all the data at once, without writing out lines of code for every field
$data = array_map('trim',$_POST); // if any field is an array, use a recursive trim call-back function here instead of php's trim
switch($data['type'])
{
case 'login':
//code block
break;
case 'register':
// inputs - 'troop_id' (select/option), 'first_name', 'last_name' 'email', 'password', 'password2'
// validate inputs
if($data['troop_id'] === '')
{
$errors['troop_id'] = "Troop is required";
}
if($data['first_name'] === '')
{
$errors['first_name'] = "First Name is required";
}
if($data['last_name'] === '')
{
$errors['last_name'] = "Last Name is required";
}
if($data['email'] === '')
{
$errors['email'] = "Email is required";
}
else if(!filter_var($data['email'],FILTER_VALIDATE_EMAIL))
{
$errors['email'] = "Email must be in correct format.";
}
if($data['password'] === '')
{
$errors['password'] = "Password is required";
}
if($data['password2'] === '')
{
$errors['password2'] = "Password Confirmation is required";
}
if(empty($errors['password']) && empty($errors['password2']) && $data['password'] != $data['password2'])
{
$errors['password2'] = "Passwords don't match";
}
// in no errors, use the submitted data
if(empty($errors))
{
$sql = "INSERT INTO users (troop_id,first_name,last_name,email,password,token) VALUES (?,?,?,?,?,?)";
$stmt = $pdo->prepare($sql);
try { // a 'local' try/catch to handle a specific database error
$stmt->execute([
$data['troop_id'],
$data['first_name'],
$data['last_name'],
$data['email'],
password_hash($data['password'], PASSWORD_DEFAULT),
$token = bin2hex(random_bytes(10))
]);
// build the link get parameters in an array, then use http_build_query, which url encodes the values, to produce the query string part of the url
$get['email'] = $data['email'];
$get['token'] = $token;
// apply htmlentities to external, unknown, dynamic values to help prevent cross site scripting
$get = array_map('htmlentities',$get);
$link = BASE_URL.'login/registration-verify.php?'.http_build_query($get);
$email_message = 'Please click on this link to verify registration:<br>';
$email_message .= "<a href='$link'>Click Here</a>";
// this function should return a true/false value that you can test and setup a message for the user when it fails
if(!sendMail($data['email'], "Registration Verification", $email_message))
{
$errors['email'] = 'Could not send your registration verification email. Site owner has been notified.';
// you would log the available information about the registration request so that you can find what's causing the problem
}
} catch (PDOException $e) {
if($e->errorInfo[1] != 1062) // duplicate index error number
{
throw $e; // re-throw the exception if not handled by this logic
}
// since there's only one unique index in this example, a duplicate error is for that index
$errors['email'] = "Email address already in use";
// if there is more than one unique index, you would build and execute a SELECT query here to find which indexes contain duplicate values
}
}
// if no errors, success
if(empty($errors))
{
$_SESSION['success_message'] = 'Your registration information has been saved. Check your email to complete the registration process.';
die(header("Refresh:0"));
}
break;
case 'forgot':
//code block
break;
}
}
Code to test for and display user/validation errors -
// output any errors
if(!empty($errors))
{
// apply any css/markup you are using to style the output
echo "<p>".implode('<br>',$errors)."</p>";
}