On my website I have plenty of form and fields, I have a system that works perfectly but is really painful and to get up and running.
This is what my system does, once you send the form all the info is sent to a class which possesses all the data and validates it. It also stores the value of the field like this $_SESSION['userUpdate']['firstName'][1] = $firstName;
If there is an error it creates a session variable like this $_SESSION['userUpdate']['firstName'][0] = 1; the 1 tells that the field was empty. If there is no error the session variable would be at 0.
If no errors where found in the validation process the data is sent to the database.
After that the form page is reloaded with :
header( 'HTTP/1.1 303 See Other' );
header( 'Location: '.curPageURL().'' );
I use that so that you cannot resend the data when reloading the page. That is the reason I'm using all these session variables.
Then with a lot of it/else if/else I check the values of the session variables and output errors and also populate the form with the data entered previously.
Let me show you an example for a firstname field.
This is the HTML code :
<label for="firstName" class="block">First Name</label>
<span>Your first name goes here.</span><?php echo $text_first_name ?>
<input type="text" id="firstName" class="mediaText" name="firstName" value="<?php echo $first_name2; ?>" onchange="needToConfirm=true" <?php echo $style_first_name ?> />
This is the validation process by the class :
$_SESSION['ui']['first_name'][1] = $this->first_name;
if (isset($this->first_name))
{
if($this->first_name == NULL)
{
$_SESSION['ui']['first_name'][0] = 1;
}
else if(minRange(3, $this->first_name))
{
$_SESSION['ui']['first_name'][0] = 2;
}
else
{
array_push($set, "FirstName = '".$db->sql_escape($this->first_name)."'");
}
}
This is the php code that handles the eventual errors :
$error_bg = "style=\"background:#EE5C42\"";
//FIRST NAME
if($_SESSION['ui']['first_name'][0] == 1)
{
$style_first_name = $error_bg;
$first_name2 = $_SESSION['ui']['first_name'][1];
}
else if($_SESSION['ui']['first_name'][0] == 2)
{
$style_first_name = $error_bg;
$first_name2 = $_SESSION['ui']['first_name'][1];
$text_first_name = "<span class=\"errorText\">Your first name must consist of at least 3 characters.</span>";
}
else
{
$first_name2 = $userdetails["FirstName"];
}
At the end of the page there is a little function to unset the session variables.
I am wondering it there is any way to make this simpler and easier to get up and running ?
If you're asking for code optimization advice, here's how I would do that:
// so you have bunch of error codes
$possible_errors = array(
'0' => '', // No error
'1' => '', // Error, but no error message
'2' => 'Your %s must consists of at least 3 characters',
...
);
// then you have form fields stored in session
// fields in session should be named like the keys in $userdetails
// 'formName' => array('FirstName' => array(0, 'German'), 'LastName' => array('1', ''))
$errors = $values = array();
foreach ($_SESSION['formName'] as $field => $element) {
if ($element[0] > 0) { // Has error
$error_code = $element[0];
$error_message = $possible_errors[$error_code];
if (!empty($error_message)) {
$errors[$field] = sprintf($error_message, $field);
}
} else {
$values[$field] = $userdetails[$field];
}
}
// in here you end up with two arrays:
// - $errors Error messages keyed by field name
// - $values Values keyed by field name
// You use them like this
<label for="firstName" class="block">First Name</label>
<span>Your first name goes here.</span><?php if (array_key_exists('FirstName', $errors)) echo $errors['FirstName']; ?>
<input type="text" id="firstName" class="mediaText" name="firstName"
value="<?php echo $values['FirstName']; ?>"
onchange="needToConfirm=true"
<?php if(array_key_exists('FirstName', $errors)):?>style="background:#EE5C42"<?php endif;?> />
I'd recommend adding in some client side validation using the very good Bassistance jQuery Validate plugin.
Related
I have a basic form with a dozen fields (I would take 3 for example):
<input type="text" name="user_first_name" class="form-control" pattern="[A-Za-z-]+" required />
<input type="text" name="user_last_name" class="form-control" pattern="[A-Za-z-]+" required />
<input type="tel" name="user_phone" class="form-control" />
...
Only the phone number can be empty, the last name and first name are obligatory and can contain only letters and dashes (the technical constraints were imposed on me by our old ERP)
I created a function to clean up all my fields that looks like this:
public function sanitizeInfo($user_first_name, $user_last_name, $user_phone) {
$user_first_name = preg_replace('/[^A-Za-z-]/', '', $user_first_name);
$user_last_name = preg_replace('/[^A-Za-z-]/', '', $user_last_name);
$user_phone = (isset($user_phone) and !empty($user_phone)) ? preg_replace('/[^A-Za-z0-9+-.)(]/', '', $user_phone) : NULL;
$array = array(
"first_name" => $user_first_name,
"last_name" => $user_last_name,
"phone" => $user_phone
);
return $array;
}
In my PHP script I make this first check:
$fields = array('user_first_name', 'user_last_name');
$error = FALSE;
foreach ($fields as $fieldname) {
if(!isset($_POST[$fieldname]) or empty($_POST[$fieldname])) {
$error = TRUE;
$message = 'err';
}
}
if (error === TRUE) {
echo "Error !"
} else {
$info = sanitizeInfo($_POST['user_first_name'], $_POST['user_last_name'], $_POST['user_phone']);
...
** QUERY **
}
I want to check, before sending this in database, that the fields are not empty (only the telephone number can be NULL)
But the problem right now is that I do not know if my non-required fields exist and especially my sanatizeInfo function is problematic because it allows to put empty fields in database
Example:
The user enters "!! -" as firstname and the sanitizeInfo function returns "" because the preg_replace to delete these characters
How to avoid this?
All you need to do is calling the function sanitizeInfo before checking empty fields and replacing your foreach loop with a simple array_search function.
This can be implemented as follows:
$fields = array('user_first_name', 'user_last_name');
$error = FALSE;
$values = sanitizeInfo($fields[0], $fields[1], #$fields[2]);
$arSear = array_search('', $values);
if ($arSear !== FALSE && $arSear != 'phone'){
$error = TRUE;
$message = 'The field `'.$arSear.'` is empty.';
}
if ($error) {
echo 'Error: '. $message;
} else {
// QUERY ....
}
As a matter of consistency, I recommend always using && and || in php versus AND and OR. This will prevent any trip ups regarding precedence. 'AND' vs '&&' as operator
I cant seem to figure out how to make a php if stament to tell if the user inputed a numeric value and in the certin range value.
<form name="heat.php" class="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<fieldset>
<legend>Get The Heat Index</legend>
Tempeture <input type="text" name="temp"><br>
Humidity <input type="text" name="hum"><br>
<input id="submit"type="submit" value="Get The Heat Index">
</feildset>
</form>
<?php
$temp=
$hum="";
if (empty($temp) && empty($hum) && ("80" <= $temp) && ($temp >= "112") && ("13" <= $hum) && ($hum >= "85")) //validates temp input
{
echo "The temperature should be a number between 80 and 112.
The humidity should be a number between 13 and 85. Please try again.";
} else{
}
?>
Once user inputs the correct data the else will happen but if its not a correct number or outside of the range value then they will get the error message.
You can do it in one check - just use filter_var
Example:
filter_var(
$value,
FILTER_VALIDATE_INT,
[
'options' => [
'max_range' => 10,
'min_range' => 4
]
]
)
This will return the value as integer for all values passed in that are an integer and between 4 and 10. (both inclusive!). If the passed value does not fit the parameters, it will return false. If you do not want that false is returned you can specify a default return value:
filter_var(
$value,
FILTER_VALIDATE_INT,
[
'options' => [
'max_range' => 10,
'min_range' => 4,
'default' => 5
]
]
)
And the working code: https://3v4l.org/JZ54r
Here's code that works as follows:
<?php
const minHum = 13;
const maxHum = 85;
const minTemp = 80;
const maxTemp = 112;
$temp = 0;
$hum = 0;
$message = "";
$arrOptions = [["options" => ["min_range"=>minTemp, "max_range"=>maxTemp]],
["options" => ["min_range"=>minHum, "max_range"=>maxHum]]];
$arrShouldBe = ["The temperature should be a number between 80 and 112.",
"The humidity should be a number between 13 and 85. Please try again."];
function failed2Validate($var,$arr){
if ( filter_var($var, FILTER_VALIDATE_INT, $arr)== false) {
return true;
}
return false;
}
function validate($temp,$hum,$arrOptions, $arrShouldBe){
$i=0;
$message = "";
$arrFuncs = [failed2Validate($temp,$arrOptions[0]), failed2Validate($hum,$arrOptions[1])];
$count = count($arrFuncs);
while ($i < $count) {
$message = $arrFuncs[$i]? $arrShouldBe[$i]: "Success";
if ($message != "Success"){
break;
}
$i++;
}
return $message;
}
/******* START ******/
if ( isset( $_POST["submit"] ) ) {
if ( !isset($_POST['temp']) || !isset($_POST['hum']) ) {
$message = "No data, No dice";
}
// check that data is numeric
else
if( ctype_digit($_POST['temp']) && ctype_digit($_POST['hum']) ) {
[$temp,$hum] = [ $_POST['temp'], $_POST['hum']];
}
else
{ //coerce data into numeric values
[$temp,$hum] = [(int) $_POST['temp'], (int) $_POST['hum']];
}
if ($message != "No data, No dice") {
$message = validate($temp,$hum,$arrOptions, $arrShouldBe);
}
echo $message;
?>
<html>
<head><title>test</title>
</head>
<body>
<form name="myform" class="form" method="post" action="<?php echo $action; ?>">
<fieldset>
<legend>Get The Heat Index</legend>
Tempeture <input type="text" name="temp"><br>
Humidity <input type="text" name="hum"><br>
<input name="submit" id="submit"type="submit" value="Get The Heat Index">
</feildset>
</form>
</body>
</html>
See simulated POST with slightly modified PHP code here.
The name attribute of the OP's form seems oddly reminiscent if a PHP filename. So, I changed it to myform. More info about the name attribute in HTML form here.
One line of code, namely $temp= will produce a parser error. Interestingly, you may write a statement, like $temp;.
One needs to be careful with logic when using empty() vs isset() since with respect to a variable that has not been assigned a value or is set to null, empty() returns true unlike isset() which returns false.
Most importantly, user-submitted data should be treated as tainted. So, in this case, the code checks to see if the user submitted values. If so, then the data is tested to see whether it is numeric. If not, then the code casts the POST data to integers. In the OP's code sample there is no code indicating that POSTed data was assigned to any variables. In fact, the OP's code never tests that a form was even submitted, therefore I inserted code to test for that circumstance.
Lastly, the comparisons need the correct order, i.e. if a user enters 90 for the temperature then the test ("80" <= $temp) will always return true, but if you reverse the operands, i.e. ($temp <= "80") then you can detect accurately whether user submitted a temperature in the desired range or if an error has occurred.
Note: I originally revised my answer having been inspired by the example that kuh-chan provides using filter_var().
I have some code written in php to validate a postcode field in my form. The code is meant to check that the field is not empty (mandatory) and matches one of 5 usable postcodes, if not it displays an alert. The problem i am having is that when i leave the field empty and hit the submit button the proper alert is show but if i enter a wrong value and hit submit the form just loads to a blank screen, can anyone spot a mistake in my code? :
<?php
if (isset($_POST['submit'])) {
$post = $_POST["post"];
$words = array('2747','2750','2753','2760','2777');
$msgp = "";
if (!empty($post)) {
foreach ($words as $item)
{
if (strpos($post, $item) !== false)
return true;
}
$msgp = '<span class="error"><b>Please enter correct postcode</b></span>';
return false;
} else if(empty($post)) {
$msgp = '<span class="error"><b>Please enter postcode</b></span>';
}
}
?>
<form name="eoiform" method="POST" action="<?php echo $_SERVER["PHP_SELF"];?>" id="eoi">
<b>Post Code</b>
<br>
<input type="text" id="post" name="post" /><?php echo $msgp; ?>
</form>
return? Return where?
When you return in your main code, it's (nearly) the same as die()'ing.
So when you return, the remaining PHP won't be executed anymore.
I'd consider to set some variable like $success = true/false; instead of returning.
You return false after $msgp = '<span class="error"><b>Please enter correct postcode</b></span>'; therefor you do not continue to the form below... remove the returns from your code to be able to handle and show an error.
You are using return. Are you in a function() {} ? If so, all your variables are in function scope. You could do global $msgp; to make the variable accessible outside of the function.
If not... then you shouldn't use return.
Change php code to
<?php
if (isset($_POST['post'])) {
$post = intval($_POST["post"],0);
$words = array(2747,2750,2756,2760,2777);
$msgp = '<span class="error"><b>'.in_array($post,$words) ? "Please enter postcode" : "Please enter correct postcode" .'</b></span>';
}
There are a lot of things that can be simplified. For example codes as int array and using in_array() function. Return statement should be used to return something from method/function using it in global scope then execution of the current script file is ended. There is no need for it here. If there are more $words values you should consider using simple REGEX /[0-9]{4}/ and preg_match()
You want to display $msgp right? Use echo $msgp;. But you can return to nowhere in your code. (put it in a function).
Try this
<?php
$post = $_POST["post"];
$words = array('2747','2750','2753','2760','2777');
$msgp = "<span class='error'><b>Please enter correct postcode</b></span>";
function check($post){
global $words;
$return=true;
if (!empty($post)) {
foreach ($words as $item)
{
if (strpos($post, $item) !== false)
//$return=true;
}
} else if(empty($post)) {
$return=false;
}
return $result;
}
$return=check($post);
if($return === true){
// echo you are right!
}
else {
echo $msgp;
}
I am creating a checkout page that requires the client to fill out his personal information as well as his credit card details (this part using stripe).
I was wondering, what is the best way to check whether the fields are filled up or not? Shall I do it in the processingPayment.php that $_POSTs the fields and processes payment, and in case the fields were not filled, I would redirect back to checkout?
Or is it a better idea to use js to check on the spot before submitting the form?
if in the processing page, I would try something like this:
if (empty($firsName) || empty($lastName) || empty($address) || empty ($city) || empty ($state) || empty($zip))
{
header('Location: checkout.php');
}
But I would need to re-send the values that were entered so the checkout page receives them and the user doesn't have to re-fill every field again...
Something like this?
foreach($_POST as $key=>$val) {
if( empty($val) ) {
echo "$key is empty";
}
}
The best method with PHP is to have an array of possible arguments:
$array = array('firstName', 'lastName');
foreach($array as $val) {
if( empty($_POST[$val]) ) {
echo "$val is empty";
}
}
Otherwise, client side validation works too, but can always be disabled. To be completely safe, use both client and server side.
You can use the session to store the entered data, but you would need to check each value separately:
PHP
<?php
session_start();
foreach ($_POST as $key => $value) {
if (strlen(trim($value)) <= 0) { //You could replace '0'
$_SESSION[$key] = $value;
}
}
?>
FORM
<form>
First name: <input type="text" value="<?php $_SESSION['firstName'] ? $_SESSION['firstName'] : ''; ?>" placeholder="First Name" />
....
</form>
The $_SESSION['firstName'] ? $_SESSION['firstName'] : ''; is the same as
if ($_SESSION['firstName']) return $_SESSION['firstName']
else return '';
it is more readable in the HTML(View) that the full if statement
$var = isset($_POST['field']) ? $_POST['field'] : '';
$var2 = isset($_POST['field2']) ? $_POST['field2'] : '';
// and so on
if( empty($var) || empty($var2) )
{
//it's empty
}
I'm using an old random() function for creating a validation code for an AJAX commenting system I found on the web (source code at LINK ).
The idea behind is pretty simple:
function Random()
{
$chars = "ABCDEFGHJKLMNPQRSTUVWZYZ23456789";
srand((double)microtime()*1000000);
$i = 0;
$pass = '' ;
while ($i <= 4)
{
$num = rand() % 32;
$tmp = substr($chars, $num, 1);
$pass = $pass . $tmp;
$i++;
}
return $pass;
}
$random_code = Random();
and then in the form, just before the SUBMIT button:
<label for="security_code">Enter this captcha code: <b><? echo $random_code; ?></b></label>
<input type="text" name="security_code" id="security_code" />
<input name="randomness" type="hidden" id="randomness" value="<?php $random_code; ?>">
My AJAX commenting system uses something like this for checking if a field is blank (ie. if there are any errors):
$errors = array();
$data= array();
[...]
if(!($data['name'] = filter_input(INPUT_POST,'name',FILTER_CALLBACK,array('options'=>'Comment::validate_text'))))
{
$errors['name'] = 'Please enter a name.';
}
if(!empty($errors)){
[...]
}
so I wrote this:
if(!($data['security_code'] = filter_input(INPUT_POST,'security_code',FILTER_CALLBACK,array('options'=>'Comment::validate_text'))))
{
$errors['security_code'] = 'You did not enter the validation code.';
}
elseif(!($data['security_code'] = $randomness))
{
$errors['security_code'] = 'You entered the validation code incorrectly. Please note that it is case sensitive.';
}
However when I click on the SUBMIT button after having inserted a random text in the validation code textfield ( test it by yourself at LINK ) I always get the "You entered the validation code incorrectly." message.
print_r($_POST) gives an empty array and then the script hangs after I click on submit:
Array
(
)
What am I missing? The original captcha code gets lost at some point in the validation process (the 3rd and 4th blocks of code).
Thanks in advance
After seeing your code here, I see that the static function validate doesn't know the variable $randomness! From your submit.php, you are making the following call:
$arr = array();
$validates = Comment::validate($arr);
The function validate doesn't know anything about the variable $randomness unless you pass such a thing to it - it is in a different scope.
Try modifying the above mentioned code as such:
$arr = array(); // no change here
$randomness = isset($_POST['randomness']) ? $_POST['randomness'] : '';
// Check for empty randomness before you validate it in Comment::validate
// so that you donot verify for '' == '' there.
$validates = Comment::validate($arr, $randomness);
And alter the validate function as follows:
public static function validate(&$arr, $randomness)
{
I know its not the elegant solution - that would require few more things that you'd learn well for yourself, this is just to show you the way...
Let me know how it goes.
instead of:
<input name="randomness" type="hidden" id="randomness" value="<?php $random_code; ?>">
write:
<input name="randomness" type="hidden" id="randomness" value="<?php echo $random_code; ?>">
also instead of:
elseif(!($data['security_code'] = $randomness))
{
$errors['security_code'] = 'You entered the validation code incorrectly. Please note that it is case sensitive.';
}
maybe this:
elseif($data['security_code'] != $randomness) {
$errors['security_code'] = 'You entered the validation code incorrectly. Please note that it is case sensitive.';
}
also, from where $data get its values? $_POST, $_GET?
print_r() it and also the $_REQUEST to light up.