Reputation: 55
I'm trying to create a registration form and validating the data submitted using PHP. But with the error messages that I've included in my PHP code, they appear on the top of the page, I would like them to appear where the default required message appears.
How the error messages appear on the page:
Heres my PHP code:
<?php
if (isset($_POST['submitted'])) {
if (!empty ($_POST['fname']))
$fname = $_POST['fname'];
else{
echo "Please enter your first name <br>";
exit;
}
if (!empty ($_POST['lname']))
$lname = $_POST['lname'];
else{
echo "Please enter your last name <br>";
exit;
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = $_POST["email"];
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
echo $emailErr;
}
}
}
?>
Heres the html code:
<form method="post" action="studentreg.php" enctype="multipart/form-data">
<div class= sregheading>
<h1 id = "sreg">Student Registeration </h1>
<p>Please fill in this form to create an account to <b> attend </b> events.</p>
</div>
<div class="container">
<hr>
<label for="first name"><b>First Name</b></label>
<input type="text" placeholder="Enter first name" name="fname" id="fname" required>
<label for="last name"><b>Last Name</b></label>
<input type="text" placeholder="Enter last name" name="lname" id="lname" required>
<label for="Personal email"><b>Personal Email</b></label>
<input type="text" placeholder="Enter Your Personal Email " name="email" id="email" required>
<label for="email-repeat"><b>Repeat Email</b></label>
<input type="text" placeholder="Repeat Your Personal Email" name="email_repeat" id="email_repeat" required>
<label for="Personal email"><b>University Email (p.s it should end in ac.uk)</b></label>
<input type="text" placeholder="Enter Your University Email " name="uni_email" id="email" required>
<label for="email-repeat"><b>Repeat University Email</b></label>
<input type="text" placeholder="Repeat Your University Email" name="uni_email_repeat" id="uni_email_repeat" required>
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="psw" id="psw" required>
<label for="psw_repeat"><b>Repeat Password</b></label>
<input type="password" placeholder="Repeat Password" name="psw_repeat" id="psw_repeat" required>
<hr>
<p>By creating an account you agree to our <a href="#">Terms & Privacy</a>.</p>
<input type="hidden" name="submitted" value="true" />
<input type="submit" name="submit" value="Submit" class="registerbtn"/>
</div>
Upvotes: 1
Views: 4600
Reputation: 33813
You can leverage more flexibility and perhaps better results if you initially configure an array mapping the field names from the form to a particular sanitising filter constant. This same array can be used for multiple operations throughout the form validation as you will see below.
Incidentally the spelling of Registeration
is incorrect - it should be Registration
!
<?php
error_reporting(E_ALL);
session_start();
$errors=array();
#helper functions to retain form field value and display associated errors
function setvalue( $name=false ){
echo ( !empty($name) && !empty($_POST[$name]) ) ? $_POST[$name] : '';
}
function displayerror( $name=false ){
global $errors; #import the errors variable into the scope of this function
if( !empty($errors[$name]) ){
foreach($errors[$name] as $error){
printf('<div class="error">%s</div>',$error);
}
}
}
if( $_SERVER['REQUEST_METHOD']=='POST' ){
$args=array(
# define the filters... can be more sophisticated than this!
# the order is important for following routines where `array_slice` is used.
'fname' => FILTER_SANITIZE_STRING,
'lname' => FILTER_SANITIZE_STRING,
'email' => FILTER_SANITIZE_EMAIL,
'email_repeat' => FILTER_SANITIZE_EMAIL,
'uni_email' => FILTER_SANITIZE_EMAIL,
'uni_email_repeat' => FILTER_SANITIZE_EMAIL,
'psw' => FILTER_SANITIZE_STRING,
'psw_repeat' => FILTER_SANITIZE_STRING,
'submitted' => FILTER_SANITIZE_STRING,
'submit' => FILTER_SANITIZE_STRING
);
# test whether all required fields are present in the POST array & have a value
foreach( array_keys($args) as $field ){
if( empty( $_POST[$field] ) )$errors[$field]=array( sprintf('%s is required.', htmlentities( $field ) ) );
}
# test whether there are unknown fields in the POST array - this might be malicious or developer oversight
foreach( $_POST as $field => $value ){
if( !in_array( $field, array_keys( $_POST ) ) )$errors[$field]=sprintf('The field %s is unexpected.', htmlentities( $field ) );
}
if( empty( $errors ) ){
# filter the POST array according to configuration above
$_POST=filter_input_array( INPUT_POST, $args );
# we are not interested in these necessarily
unset( $_POST['submitted'] );
unset( $_POST['submit'] );
# extract sanitised POST variables
extract( $_POST );
# extract all the password fields & email fields into new arrays
$pwds=array_keys( array_slice( $args, 6, 2 ) );
$emails=array_keys( array_slice( $args, 2, 4 ) );
$personal=array_keys( array_slice( $args, 2, 2 ) );
$educational=array_keys( array_slice( $args, 4, 2 ) );
/*
validate email addresses
------------------------
[1] select which fields to validate
[2] run automated filter as basic first step.
[3] test specific .ac.uk tld
*/
foreach( $emails as $name ){
if( !filter_var( ${$name}, FILTER_VALIDATE_EMAIL ) ){
$errors[$name][]=sprintf('"%s" is not a valid email address!', htmlentities( ${$name} ) );
}
}
# validate educational email tld
foreach( $educational as $name ){
if( substr( ${$name}, -6 ) !== '.ac.uk' ){
$errors[$name][]=sprintf('Invalid email "%s" - it must end with .ac.uk', htmlentities( ${$name} ) );
}
}
# Confirm that email addresses match
if( ${$personal[0]}!==${$personal[1]} ){
foreach( $personal as $field )$errors[$field][]='Personal emails do not match';
}
if( ${$educational[0]}!==${$educational[1]} ){
foreach( $educational as $field )$errors[$field][]='Educational emails do not match';
}
/*
validate password length & complexity
-------------------------------------
complexity is NOT tested here.
*/
$minlength=8;
$maxlength=128;
foreach( $pwds as $name ){
if( empty( ${$name} ) )$errors[$name][]=sprintf('The password field %s is required', htmlentities( $name ) );
if( strlen( ${$name} ) < $minlength )$errors[$name][]=sprintf('The password %s is too short! Minimum length is: %d',$name,$minlength);
if( strlen( ${$name} ) > $maxlength )$errors[$name][]=sprintf('The password %s is too long! Maximum length is: %d',$name,$maxlength);
}
# test whether passwords match or not.
if( ${$pwds[0]} !== ${$pwds[1]} ){
foreach( $pwds as $field )$errors[$field][]='Passwords do not match';
}
# do whatever end processing with valid data is required and redirect if necessary
# if the processing gets to this stage then all is, more or less, OK.
if( empty( $errors ) ){
$sql='insert into `students` () values ();';
exit('Run: '.$sql.' and relax in a job well done');
}
}else{
# display errors - the user should not see these as these
# are development issues or possibly malicious.
foreach( $errors as $error )printf('%s<br />', strip_tags( $error ) );
exit();
}
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Student Registration</title>
<style>
html,html *{box-sizing:border-box;font-family:monospace}
label{display:block;padding:0.5rem;margin:0.5rem auto;width:50%;float:none;clear:both;}
label input{margin:auto;float:right;}
hr{width:50%;margin:2rem auto;float:none;border:none;border-top:1px dotted grey}
.sregheading,section{width:50%;float:none;margin:auto}
.error{color:red;width:100%;margin:0.1rem 0;font-size:smaller;}
.error:before{content:'*';margin:0 0.25rem;font-weight:bold}
section{width:100%;margin:0 0 2rem 0;}
section.footer{width:50%;margin:auto}
</style>
</head>
<body>
<!--
removed for testing
-->
<!-- action='studentreg.php' -->
<form method='post' enctype='multipart/form-data'>
<div class='sregheading'>
<h1 id='sreg'>Student Registration</h1>
<p>Please fill in this form to create an account to <b>attend</b> events.</p>
</div>
<div class='container'>
<hr />
<section data-id='user-names'>
<label>
<b>First Name</b>
<input type='text' placeholder='Enter first name' name='fname' value='<?php setvalue('fname');?>' required />
<?php
displayerror('fname');
?>
</label>
<label>
<b>Last Name</b>
<input type='text' placeholder='Enter last name' name='lname' value='<?php setvalue('lname');?>' required />
<?php
displayerror('lname');
?>
</label>
</section>
<section data-id='personal-emails'>
<label>
<b>Personal Email</b>
<input type='text' placeholder='Enter Your Personal Email ' name='email' value='<?php setvalue('email');?>' required />
<?php
displayerror('email');
?>
</label>
<label>
<b>Repeat Email</b>
<input type='text' placeholder='Repeat Your Personal Email' name='email_repeat' value='<?php setvalue('email_repeat');?>' required />
<?php
displayerror('email_repeat');
?>
</label>
</section>
<section data-id='educational-emails'>
<label>
<b>University Email (p.s it should end in ac.uk)</b>
<input type='text' placeholder='Enter Your University Email ' name='uni_email' value='<?php setvalue('uni_email');?>' required />
<?php
displayerror('uni_email');
?>
</label>
<label>
<b>Repeat University Email</b>
<input type='text' placeholder='Repeat Your University Email' name='uni_email_repeat' value='<?php setvalue('uni_email_repeat');?>' required />
<?php
displayerror('uni_email_repeat');
?>
</label>
</section>
<section data-id='passwords'>
<label>
<b>Password</b>
<input type='password' placeholder='Enter Password' name='psw' required />
<?php
displayerror('psw');
?>
</label>
<label>
<b>Repeat Password</b>
<input type='password' placeholder='Repeat Password' name='psw_repeat' required />
<?php
displayerror('psw_repeat');
?>
</label>
</section>
<hr />
<section class='footer'>
<p>By creating an account you agree to our <a href='#'>Terms & Privacy</a>.</p>
<input type='hidden' name='submitted' value='true' />
<input type='submit' name='submit' value='Submit' class='registerbtn'/>
</section>
</div>
</form>
</body>
</html>
Upvotes: 0
Reputation: 11
By assigning the errors you detect with PHP to a variable, you can check the existence of that variable in your html file and view the error wherever you want.
Heres my PHP code:
<?php
if (isset($_POST['submitted'])) {
if (!empty ($_POST['fname']))
$fname = $_POST['fname'];
else{
$error1 = "Please enter your first name <br>";
exit;
}
if (!empty ($_POST['lname']))
$lname = $_POST['lname'];
else{
$error2 = "Please enter your last name <br>";
exit;
}
if (empty($_POST["email"])) {
$error3 = "Email is required";
} else {
$email = $_POST["email"];
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error4 = "Invalid email format";
}
}
}
?>
Heres the html code:
<form method="post" action="studentreg.php" enctype="multipart/form-data">
<div class= sregheading>
<h1 id = "sreg">Student Registeration </h1>
<p>Please fill in this form to create an account to <b> attend </b> events.</p>
</div>
<div class="container">
<hr>
<label for="first name"><b>First Name</b></label>
<?php if(isset($error1)){echo $error1}; ?>
<input type="text" placeholder="Enter first name" name="fname" id="fname" required>
<label for="last name"><b>Last Name</b></label>
<?php if(isset($error2)){echo $error2}; ?>
<input type="text" placeholder="Enter last name" name="lname" id="lname" required>
<label for="Personal email"><b>Personal Email</b></label>
<?php
if(isset($error3)){echo $error3};
if(isset($error4)){echo $error4};
?>
<input type="text" placeholder="Enter Your Personal Email " name="email" id="email" required>
<label for="email-repeat"><b>Repeat Email</b></label>
<input type="text" placeholder="Repeat Your Personal Email" name="email_repeat" id="email_repeat" required>
<label for="Personal email"><b>University Email (p.s it should end in ac.uk)</b></label>
<input type="text" placeholder="Enter Your University Email " name="uni_email" id="email" required>
<label for="email-repeat"><b>Repeat University Email</b></label>
<input type="text" placeholder="Repeat Your University Email" name="uni_email_repeat" id="uni_email_repeat" required>
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="psw" id="psw" required>
<label for="psw_repeat"><b>Repeat Password</b></label>
<input type="password" placeholder="Repeat Password" name="psw_repeat" id="psw_repeat" required>
<hr>
<p>By creating an account you agree to our <a href="#">Terms & Privacy</a>.</p>
<input type="hidden" name="submitted" value="true" />
<input type="submit" name="submit" value="Submit" class="registerbtn"/>
</div>
This is my first comment, I hope I was helpful.
Upvotes: 1