Empty data added to text file in PHP - php

I am doing a school project which require me to create a buy & sell website.
I have a form for user to input values such as name, email, etc. After it is filled up, they will press "submit" button, and the values will be written to my txt file.
However, I realized that, empty data are being written into the txt file as well, causing my text file to look like this
It happens when user click on the navigation button to access the form. Even when no values are entered. Empty spaces are written to my txt just by accessing the form.
Below is my code.
<?php
// define variables and set to empty values
$sellerNameErr = $emailErr = "";
$sellerName = $email = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["sellerName"])) {
$sellerNameErr = "Name is required";
}else {
$sellerName = test_input($_POST["sellerName"]);
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
}else {
$email = test_input($_POST["email"]);
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
}
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<form name="sell" action="" method="post">
<p><span class = "error">* required field.</span></p>
<p>Seller Name: <input type="text" name="sellerName" />
<span class = "error">* <?php echo $sellerNameErr;?></span></p>
<p>Email: <input type="text" name="email" />
<span class = "error">* <?php echo $emailErr;?></span></p>
<input type="submit" name="Submit" value="Submit" />
<?php
$fp=fopen("buynsell.txt", "ab");
fwrite($fp,"$sellerName\t $email\r\n");
fclose($fp);
?>
</form>
How can I prevent empty data from being added to my log file?

Before writing to the file, you need to verify that $sellerName and $email have values and that there were no errors.
if ($sellerName && $email && !$sellerNameErr && !$emailErr) {
$fp=fopen("buynsell.txt", "ab");
fwrite($fp,"$sellerName\t $email\r\n");
fclose($fp);
}
The way you have it written now you don't need to do anything to check that those variables are set because you're initializing them all to empty strings, but if you change that, you should use empty()/!empty() instead to avoid undefined variable notices.
If you move the file writing PHP code inside the post handling code at the top so that it will only run when the form has been posted, after the validation code that checks if the inputs are empty, then you should be able to just check for errors only. if (!$sellerNameErr && !$emailErr) { .... Personally, I think it makes more sense for it to be there anyway. It's easier to read if all your PHP code is together, and there's no need for that code to be down there in the form.

Mark, there are many ways to prevent that empty data does not get into your business logic.
As for your project the most simple way to achieve this would be to set an additional attribute within your html markup.
As for HTML5 this could by your first solution:
<input type="text" name="usrname" required>
https://www.w3schools.com/tags/att_input_required.asp
Not that really efficient as only on client side, so you should also implement this on your server side.
empty($_POST['user']) will not work as you are never posting that value, therefore you must add an value attribute to your input field:
<input type="text" name="user" value="" />

Related

PHP form validation doesn't work

I'm all new to PHP and JavaScript, just learning web development and I'm trying all sort of things in my free time, however, there is one thing I cannot find a solution for.
I have a form that would be collecting only 4 datas, Name, Date of Birth, Email and Phone number. All fields are required for further data procession. I literally tried every single thing I found on Google, but it still doesn't work. The form simply saves all sort of data into the database, without checking the input fields.
Later on I'd like the code to validate the form, display any errors on the same page not on a different ".php" one and also send 2 emails one as a confirmation for the person and one for notifying me about a form submission. What should I do/change to achieve that? I feel quite stuck atm.
my form:
<form class="contactform" id="cfrm" action="process.php" method="post">
<div class="f-data">
<input class="f-error" name="uname" placeholder="NAME" type="text" required="required" data-error="Name is required.">
</div>
<div class="clear"></div>
<div class="f-data">
<select name="birthday" id="forminput" aria-required="true" aria-invalid="false">
<option value="11">11</option>
<option value="12">12</option>
</select>
<select name="birthyear" id="forminput" aria-required="true">
<option value="1900" selected="selected">1900</option>
<option value="2001">2001</option>
</select>
</div>
<div class="f-data">
<input class="f-error" name="uemail" placeholder="EMAIL" type="text" required="required" data-error="Email is required.">
</div>
<div class="f-data">
<input class="f-error" name="uphone" placeholder="PHONE" type="text" required="required" data-error="Phone is required.">
</div>
<div class="clear"></div>
<div class="submit">
<p>
<input type="submit" value="submit" name="submit">
</p>
</div>
and the process.php
<?php
require "connection.php";
require "others/phpmailer/PHPMailerAutoload.php";
//form data
$connection = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
$Name = $connection->real_escape_string($_POST['uname']);
$DoB = $connection->real_escape_string($_POST['birthyear'] . '-' .
$_POST['birthmonth'] . '-' . $_POST['birthday']);
$inputDoB = date("Y-m-d",strtotime($DoB));
$Email = $connection->real_escape_string($_POST['uemail']);
$Phone = $connection->real_escape_string($_POST['uphone']);
if (strlen($agree) == 0) $agree = 0;
// validating
if(isset($_POST['submit']));
{
if(empty($_POST['uname']))
{
$msg_name = "You must enter name";
$name_subject = $_POST['uname'];
$name_pattern = '/^[a-zA-Z ]*$/';
preg_match($name_pattern, $name_subject, $name_matches);
if(!$name_matches[0])
$msg2_name = "Only alphabets and white space allowed";
}
if(empty($_POST['uemail']))
{
$msg_email = "You must enter your email";
$email_subject = $_POST['uemail'];
$email_pattern = '/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/';
preg_match($email_pattern, $email_subject, $email_matches);
if(!$email_matches[0]) $msg2_email = "Must be a valid email address";
}
if($_POST['uphone'])
{
$phone = $_POST['uphone'];
preg_match('/^[_a-z0-9-]+(.[_a-z0-9-]+)*#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z {2,3})$/i', $phone, $phone_match);
if(!$phone_match[0]) $msg_phone = "Must be a valid phone number";
if(strlen($phone)!='8') $msg2_phone = "Must be at least 8 characters long";
}
}
//save to db
$query = "INSERT INTO form (Name,DoB,Email,Phone,Date) VALUES ('$Name','$DoB','$Email','$Phone', CURRENT_TIMESTAMP)";
$success = $connection->query($query);
if (!$success) {
die("Couldn't enter data: ".$connection->error);
}
echo "Thank You For Contacting Us";
?>
As for your display of inline error messages, what I would recommend doing is only making use of one page to handle the main form 'logic', and another include() to represent the raw HTML markup fo the form itself. The 'logic' page would be where you direct your visitors as the 'form'.
Inside of your if(isset($_POST['submit'])), you would check the data that is submitted. If it is valid, you go ahead and process the submission. If it is invalid, you raise an error, and show the form again. The form is also shown by default.
This is shown in the following semi-pseudocode:
$error = ''; // Nothing is wrong at first
if(isset($_POST['submit'])) {
// Raise error messages based on submission
if(empty($_POST['uname'])) {
$error = "You must enter name";
}
if(empty($_POST['email'])) {
$error = "You must enter email";
}
// Show the form if there are errors
if ($error) {
include('form.php');
}
// Process the submission if there aren't
else {
//$query = ...
mail($Email, $email_subject, $msg_email);
}
}
else {
include('form.php');
}
With form.php conditionally checking for $error:
<?php
if ($error !== '') {
// Output the error message in a fancy way
echo "<span class='error'>" . $error . "</span>";
}
?>
<form> ... </form>
As for sending the two emails, you're practically there! You already have $msg_email, $email_subject and $Email. You're just looking to make use of PHP's mail() function:
mail($Email, $email_subject, $msg_email);
Note that you'll probably want to add the fourth parameter (headers) in there as well.
I also note that you currently have a semicolon in if(isset($_POST['submit']));{, which will prevent the block from triggering. Make sure you remove this.
Hope this helps! :)
While formatting your code for question clarity I think I found the issue.
You have 2 formatting issues that would cause this sort of issue.
1) You have a semicolon preventing your if from being a block conditional
if(isset($_POST['submit']));
with that semicolon there the block will run separated and simply act as a scope separator.
2) Your Regex isn't complete
preg_match('/^[_a-z0-9-]+(.[_a-z0-9-]+)*#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z {2,3})$/i', $phone, $phone_match);
In your last capture group (.[a-z {2,3}) you don't have a closing square bracket for the [a-z] character selector it should be (.[a-z]{2,3})
I would also point out that you are setting$msg_name and $msg2_name but I don't see them used anywhere and you don't stop execution on error so the process just continues through to the query even though you said you want it to stop.

How to make multiple AJAX queries after user input?

This seems like such a simple thing, but I have not been able to find adequate guidance on it for the life of me. I have only been able to find things about successive AJAX queries regardless of user input, like this or this.
What I'm trying to do is create a survey such that after a user answers a question, the website replaces the question with the next question, and so on.
Here's what I have so far (in a .php file):
In <head>, I have a function for each successive element to call:
<script type="text/javascript">
function nextPage(url) {
$("#consent-form").empty();
$("#consent-form").load(url);
}
</script>
Maybe that's just not how it's done. I have no idea. Like I said, I have not been able to find adequate help on this. As far as I can tell, empty() should not delete #consent-form, but only its content and children, which is exactly the behavior I want.
This is the initial html and php for the div I want to swap out after each answered question:
<div id="consent-form">
<?php
// Check for a valid email address.
$email = $emailErr = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["email"])) {
$emailErr = "* Your email address is required.";
} else {
$email = test_input($_POST["email"]);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "* Please enter a valid email address.";
} else {
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$query = "INSERT INTO survey VALUES ('" . $email . "','" . $actual_link . "','','')";
mysql_query($query);
echo '<script type="text/javascript">'
, 'nextPage("survey.php");'
, '</script>'
;
}
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<p>
[Consent form text]
</p>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
Please enter your email address: <input type="text" name="email" value="<?php echo $email;?>">
<span class="error"> <?php echo $emailErr;?></span>
<br>
<input type="submit" value="Begin Study">
</form>
</div>
As I'm sure you can tell, I'm trying to do some form validation there.
This succcessfully injects the content of the next page ("survey.php") into the consent-form div. "survey.php" includes the following, using the nextPage() function shown above:
$("#csp_form").on('submit', function() {
nextPage("other.php");
});
But this fails to inject the consent-form div with "other.php".
Now, however, not even the form validation works. According to Firebug, the jquery library has raised some sort of error, even when I comment out all the jquery and javascript functions, and it's stuck in some perpetual loading operation. (This issue has been fixed.)
I am about to start throwing things. I have tried many different other techniques, but none of them worked and I have lost track of them. Hopefully this latest version will be sufficient to get guidance on this.
Sorry all that was so long, but usually people complain that there's too little information, so I wanted to make sure to include everything.
EDIT:
Per request, here's the current full content of survey.php (with the text content changed for privacy purposes):
<script type="text/javascript">
$("#icecream_form").on('submit', function() {
nextPage("other.php");
return false;
});
</script>
<br>
<h2>What's your favorite ice cream flavor?</h2>
<form method="post" id="icecream_form">
<input type="radio" name="icecream" value="vanilla"> Vanilla
<br>
<input type="radio" name="icecream" value="chocolate"> Chocolate
<br>
<input type="radio" name="icecream" value="other"> Something else
<br>
<input type="radio" name="icecream" value="none" checked> I don't have a favorite.
<br>
<br>
<input type="submit" name="icecream_submit" value="Go" onsubmit="return(false)">
</form>
After hitting submit, the content from consent-form comes back with an error message from the email form ("Please enter an email address"), implying that the email form was posted again. I cannot comprehend how that is possible if all the stuff from that div had truly been replaced by the stuff in survey.php.
I believe the issue was just that I was missing $(document).ready(function () { before $("#icecream_form").on('submit', function() {. This enabled return false; to actually work.
However, I also swapped out the PHP form validation with a jQuery version and deleted the nextPage() function in lieu of just having each page have their own .load(), so those things may also have made a difference.

PHP code checking if field is empty is not working

I am trying to make a "form" of the type "text" which will check whether an email is valid or not. I first tried to check if the text field was empty by making an if statement, but it didnt work, and it instead ran the "else" option of the statement. How do I fix it so it actually checks if the text field is empty? Here is the code.
INDEX.php:
<?php
include 'connection.php';
echo "<p> Example Text </p>";
?>
<h1> Submit email address </h1>
<form action = "create.php" method = "post">
<input type ="text" name = "email" value = "" />
<br />
<input type = "submit" name = "submit" />
</form>
Create.php :
<?php
include 'connection.php';
$email = $_POST['email'];
if(!isset($email)){
echo "please fill out the form";
header ('Location: index.php');
}
else{
echo "Successive login";
}
?>
When doing:
$email = $_POST['email'];
You are in fact setting $email so the !isset() will return false (meaning that it is NOT not isset)
instead you need to check if it is not empty
if(!empty($email)){
}
else{
}
================
EXTRA
Here is an example of how how you can check valid email addresses:
if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
echo("$email is a valid email address");
} else {
echo("$email is not a valid email address");
}
Also check out my PHP function that checks to see if the email is valid and can receive emails by connecting to the mail server and verifying it:
https://github.com/hbattat/verifyEmail
I did that. It did work when I removed the header code as well, but I
want the echo to be displayed in index.php rather than in a new page
(create.php). How do i do that? – tomSurge 3 hours ago
When you submit to the create.php basically you load the create.php page with some post parameters. So anything you display there will not be displayed in index.php because you are not in the same page.
Instead you could post to the same page index.php and do the create process there:
<?php
include 'connection.php';
if($_SERVER['REQUEST_METHOD'] == 'post'){ //check if the page was requested via post method (that means the form was submitted)
if(!isset($email)){
echo "please fill out the form";
}
else{
echo "Successive login";
}
}
echo "<p> Example Text </p>";
?>
<h1> Submit email address </h1>
<form action = "index.php" method = "post">
<input type ="text" name = "email" value = "" />
<br />
<input type = "submit" name = "submit" />
</form>
OR
You could use AJAX and not load the page when posting the info to create.php and just display the response message:
<?php
include 'connection.php';
echo "<p> Example Text </p>";
?>
<!-- include jQuery in the header of your html -->
<script src="LINK TO jQUERY .js file"></script>
<script type="text/javascript">
$(document).ready(function(){
//trigger this when the form is submitted
$('form').on('submit', function(e){
//prevent default submission and reload of the page
e.preventDefault();
//post the date to the create.php file using ajax
//get the form data
var formData = $(this).serialize();
$.post('create.php', fomrData, function(response){
var result = parseJSON(response);
$('#msg').text(result.msg);
}
});
});
});
</script>
<h1> Submit email address </h1>
<form action = "create.php" method = "post">
<input type ="text" name = "email" value = "" />
<br />
<input type = "submit" name = "submit" />
</form>
create.php
<?php
include 'connection.php';
$email = $_POST['email'];
$result = array();
if(!isset($email)){
$result['status'] = 'fail';
$result['msg'] = "please fill out the form";
}
else{
$result['status'] = 'success';
$result['msg'] = "Successive login";
}
//echo the json
echo json_encode($result);
?>
isset() only checks if the variable is set. You need to use empty($email) instead.
Replace isset with empty and it should work as you want.
If I understand your question, you have to change the statement to if(!empty($email)) Also, if you want to check if the email is in the correct format, please use a regex to do so. isset() only checks for null
You can also test for submission of something (anything) in the posted email field with:
'' == $_POST['email']
As others have suggested, empty($_POST['email']) works too, just showing another option.
Displaying the Error Message
If you want the error message to appear on index.php then you need to pass the message or some sort of flag from the create.php page (where the error is discovered) to the index.php page (where the error message is displayed).
To demonstrate a bare-bones example (one of many ways to accomplish this), first I added a PHP variable to the form. Notice the line containing echo $_GET['error']; immediately after the email input element:
index.php (form):
<form action="create.php" method="post">
<input type="text" name="email" value="" />
<?php if (isset($_GET['error'])) { echo $_GET['error']; } ?>
<br />
<input type="submit" name="submit" />
</form>
...and, instead of echo'ing the message in the create.php script, send the message along to the index.php script in the URL query:
create.php (email check):
if ( '' == $_POST['email'] ) {
header('Location: index.php?error=please+fill+out+the+form');
}
Additionally, I recommend you use this (PHP server-side validation) as a backup to a Javascript client-side validation solution. Nicer for your website visitors and uses fewer server resources.
Another way is to just add a required="" to your input Here is an example https://jsfiddle.net/57s38s2e/

PHP: Refresh page on invalid form submit

How can I refresh a page with a form on submission pending the outcome of the submitted data and display a result.
e.g I have a page with a form:
<form action="" method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
The engine that handles the form is external, but required in the page:
require_once 'form_engine.php';
form_engine.php checks the input,
$success = "true";
$errorMessage = " ";
$name = $_POST['name'];
if ( $name == '') {
$errorMessage = 'Please enter your name';
$success = false;
}
else (if $success = true) {
// do something with the data
}
The form page contains the result:
<form action="" method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
<p><?php echo $errorMessage; ?></p>
Will the error message get displayed after the form is submitted incorrectly? Or do I have to use a session to store it?
You need something like this:
if (!isset($_POST['name']))
instead of
if ( $name == 'name')
UPDATE
Try this, it should give you the idea:
<?php
$errorMessage = false;
if (isset($_POST['submit'])) {
if (!isset($_POST['name']) || $_POST['name']=='') {
$errorMessage = 'Please enter your name';
}
else {
// do something with the data
echo "Success!!";
}
}
?>
<form method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="submit" name="submit" />
</form>
<p><?php if ($errorMessage) echo $errorMessage; ?></p>
Note: leaving out the action attribute will just submit the form to the current page
Note 2: The PHP here could very well be stored in another page. Using require() is the same as putting the code directly into the page.
You can use redirect on php side:
header('Location: www.mysite.com/index.php');
You seem to be a little confused in terms of the exact process that occurs in terms of rendering a page, as do some of those commenting. You do not need to use sessions to solve this problem. There is no need to store anything server-side between page requests because the user's browser with retain everything that you need, at least for this situation. My guess is the others took you mentioning an "external engine" and thought that the form would be submitting away to a different site/page.
form loops
Below is a diagram showing a typical form request loop:
You do not have to do this, as coding is as much about personal preference to anything else, but typically people will design their form to submit back to the same URI that generated it — as you seem to be doing in your example, by leaving the action attribute blank. By doing this, as long as you embed everything you wish to pass back to the server side within the form — each time the user submits — that information will be resent and be available in PHP.
Obviously you need to be wary of what information might constitute as sensitive, as this data should only ever be written into markup if your requests are protected by HTTPS/SSL. You should also filter/escape any user input to prevent markup injection into your site. You can prevent many problems by using htmlentities, however this can cause issues depending on the values you are trying to capture from the user. Because you are using double quoted HTML attributes (the right way to do them ;) I have not set the ENT_QUOTES option.
back to the point
So in the above loop the user will be shown the form for the first time, and after any subsequent submit, which means that each time your PHP notices that there is an error you can just add your message into the page flow. The trick with this kind of system is what exactly do you do once the form is fully complete. To get out of the loop most people will use a header location call:
<?php
require_once 'form_engine.php';
$name = !empty($_POST['name']) ? trim($_POST['name']) : '';
$name = htmlentities($name);
if ( $success ) {
header('location: next-step.php');
exit;
}
?>
<form action="" method="post">
<input type="name" value="<?php echo $name; ?>" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
<?php
if ( $errorMessage ) {
echo "<p>$errorMessage</p>";
}
?>
form engine repairs
You should also rectify your form_engine.php as per my comments above and Shekhar Joshi's answer, although I would keep the header code outside of your engine logic, and leave that decision to the code that requires in the engine — as the above does.
may be, you are looking for this! the header() method.
$success = true;
$errorMessage = " ";
$name = $_POST['name'];
if(isset($_POST['name'])) {
if ( $_POST['name'] == '') {
$errorMessage = 'Please enter your name';
$success = false;
header('Location: www.something.com/some.php');
}
else if ($success == true) {
// do something with the data
}
}

PHP Show error messages in order and re-display correct fields

I have an email form that checks three fields, name, valid email and comments. But the way it's set up now, since name and comments are in one function it first checks name and comments even if email is not valid, how can I re-write it so it checks the fields in order. Also, I would like to re-display the fields that have no errors, so the user doesn't have to type again. Please help. Thanks
<?php
$myemail = "comments#myemail.com";
$yourname = check_input($_POST['yourname'], "Enter your name!");
$email = check_input($_POST['email']);
$phone = check_input($_POST['phone']);
$subject = check_input($_POST['subject']);
$comments = check_input($_POST['comments'], "Write your comments!");
if (!preg_match("/([\w\-]+\#[\w\-]+\.[\w\-]+)/", $email))
{
show_error("Enter a valid E-mail address!");
}
exit();
function check_input($data, $problem='')
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
if ($problem && strlen($data) == 0)
{
show_error($problem);
}
return $data;
}
function show_error($myError)
{
?>
<!doctype html>
<html>
<body>
<form action="myform.php" method="post">
<p style="color: red;"><b>Please correct the following error:</b><br />
<?php echo $myError; ?></p>
<p>Name: <input type="text" name="yourname" /></P>
<P>Email: <input type="text" name="email" /></p>
<P>Phone: <input type="text" name="phone" /></p><br />
<P>Subject: <input type="text" style="width:75%;" name="subject" /></p>
<p>Comments:<br />
<textarea name="comments" rows="10" cols="50" style="width: 100%;"></textarea></p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
<?php
exit();
}
?>
First off, I would suggest you validate ALL of the fields at once, and display all appropriate error messages on the form. The primary reason is that it can be bad user experience if they have to submit your form a whole bunch of times because they have to address one error at a time. I'd rather correct my email address, password, comments, and selection in one try instead of fixing one at a time just to reveal what the next error is.
That said, here are some pointers on validating the form like you want. This is typically how I approach a form doing what you want to do. This assumes your form HTML and form processor (PHP) are together in the same file (which is what you have now). You can split the two, but the methods for doing that can be a bit different.
Have one function or code block that outputs the form and is aware of your error messages and has access to the previous form input (if any). Typically, this can be left outside of a function and can be the last block of code in your PHP script.
Set up an array for error messages (e.g. $errors = array()). When this array is empty, you know there were no errors with the submission
Check to see if the form was submitted near the top of your script before the form is output.
If the form was submitted, validate each field one at a time, if a field contained an error, add the error message to the $errors array (e.g. $errors['password'] = 'Passwords must be at least 8 characters long';)
To re-populate the form inputs with the previous values, you have to store the entered values somewhere (you can either just use the $_POST array, or sanitize and assign the $_POST values to individual variables or an array.
Once all the processing is done, you can check for any errors to decide whether the form can be processed at this point, or needs new input from the user.
To do this, I typically do something like if (sizeof($errors) > 0) { // show messages } else { // process form }
If you are re-displaying the form, you simply need to add a value="" attribute to each form element and echo the value that was submitted by the user. It is very important to escape the output using htmlspecialchars() or similar functions
With those things in place, here is some re-work of your form to do that:
<?php
$myemail = "comments#myemail.com";
$errors = array();
$values = array();
$errmsg = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
foreach($_POST as $key => $value) {
$values[$key] = trim(stripslashes($value)); // basic input filter
}
if (check_input($values['yourname']) == false) {
$errors['yourname'] = 'Enter your name!';
}
if (check_input($values['email']) == false) {
$errors['email'] = 'Please enter your email address.';
} else if (!preg_match('/([\w\-]+\#[\w\-]+\.[\w\-]+)/', $values['email'])) {
$errors['email'] = 'Invalid email address format.';
}
if (check_input($values['comments']) == false) {
$errors['comments'] = 'Write your comments!';
}
if (sizeof($errors) == 0) {
// you can process your for here and redirect or show a success message
$values = array(); // empty values array
echo "Form was OK! Good to process...<br />";
} else {
// one or more errors
foreach($errors as $error) {
$errmsg .= $error . '<br />';
}
}
}
function check_input($input) {
if (strlen($input) == 0) {
return false;
} else {
// TODO: other checks?
return true;
}
}
?>
<!doctype html>
<html>
<body>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post">
<?php if ($errmsg != ''): ?>
<p style="color: red;"><b>Please correct the following errors:</b><br />
<?php echo $errmsg; ?>
</p>
<?php endif; ?>
<p>Name: <input type="text" name="yourname" value="<?php echo htmlspecialchars(#$values['yourname']) ?>" /></P>
<P>Email: <input type="text" name="email" value="<?php echo htmlspecialchars(#$values['email']) ?>" /></p>
<P>Phone: <input type="text" name="phone" value="<?php echo htmlspecialchars(#$values['phone']) ?>"/></p><br />
<P>Subject: <input type="text" style="width:75%;" name="subject" value="<?php echo htmlspecialchars(#$values['subject']) ?>" /></p>
<p>Comments:<br />
<textarea name="comments" rows="10" cols="50" style="width: 100%;"><?php echo htmlspecialchars(#$values['comments']) ?></textarea></p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
I have a more advanced example which you can see here that may give you some guidance as well.
Hope that helps.
The simplest option is to use a form validation library. PHP's filter extension, for example, offers validation and sanitization for some types, though it's not a complete solution.
If you insist on implementing it yourself, one issue you'll have to consider is what counts as the order: the order of the elements in the form or the order of the user input in $_POST. On most browsers, these should be the same, but there's no standard that enforces this. If you want to go off of form order, you'll need to define the form structure in one place, and use that information to do things like generating or validating the form (a consequence of the Don't Repeat Yourself (DRY) principle). Iterating over the appropriate structure will give you the order you desire: looping over the form gives you form order, whereas looping over $_POST gives you user input order.
It looks like you want to more than simply validate the data; you also want to prepare it for use, a process called "sanitization".
When it comes to sanitization, define different kinds of sanitizers, rather than a single check_input function. Specific sanitizers could be functions, or objects with an __invoke method. Create a map of form fields to sanitizers (for example, an array of input name to sanitizer callbacks). The order of the elements in the mapping sets the order of the sanitization; if you use a single structure to define the form information, the display order and sanitization order will thus be the same.
Here's a very broad outline:
# $fields could be form structure or user input
foreach ($fields as $name => $data) {
# sanitize dispatches to the appropriate sanitizer for the given field name
$form->sanitize($name, $data);
# or:
//sanitize($name, $data);
# or however you choose to structure your sanitization dispatch mechanism
}
As for setting an input's value to the user-supplied data, simply output the element value when outputting the element. As with all user input (really, all formatted output), properly escape the data when outputting it. For HTML attributes, this means using (e.g.) htmlspecialchars. Note you should only escape outgoing data. This means your sanitization functions shouldn't call htmlspecialchars.
You can improve usability by placing each error next to the corresponding input, adding an "error" class to the element and styling the "error" class to make it stand out. Improve accessibility by wrapping <label> elements around the label text.
Use this structure of script:
<?php
$errors = array();
if (isset($_POST['send'])) {
// check data validity
if (!mailValid($_POST['email']))
$errors[] = 'Mail is not valid';
...
// send data by email
if (!$errors) {
// send mail and redirect
}
}
?>
<html>
...
<?php
if ($errors) {
// display errors
foreach ($errors as $error) {
echo "$error<br />";
}
}
?>
<form ...>
...
Email: <input type="text" name="email" value="<?php echo isset($_POST['email']) ? htmlspecialchars($_POST['email']) : '' ?>" />
...
</form>
...
</html>
You could always do it like this, using filter_var and in_array checks:
<?php
$myemail = "comments#myemail.com";
//Pre made errors array
$errors=array('name'=>'Enter Your name',
'email'=>'Please enter valid email',
'phone'=>'Please enter valid phone number',
'subject'=>'Please enter valid subject, more then 10 chars',
'comment'=>'Please enter valid comment, more then 10 chars');
//Allowed post params and its validation type
$types = array('name'=>'string',
'email'=>'email',
'phone'=>'phone',
'subject'=>'string',
'comment'=>'string');
//A simple validation function using filter_var
function validate($value,$type){
switch ($type){
case "email":
return ((filter_var($value, FILTER_VALIDATE_EMAIL))?true:false);
break;
case "phone":
return ((preg_match("/^[0-9]{3}-[0-9]{4}-[0-9]{4}$/", $value))?true:false);
break;
case "string":
return ((strlen($value) >=10 )?true:false);
break;
default:
return false;
break;
}
}
//If forms been posted
if(!empty($_POST) && $_SERVER['REQUEST_METHOD'] == 'POST'){
//Assign true, if all is good then this will still be true
$cont=true;
$error=array();
foreach($_POST as $key=>$value){
//if key is in $types array
if(in_array($key,$types)){
//If validation true
if(validate($value, $types[$key])==true){
$$key=filter_var($value, FILTER_SANITIZE_STRING);
}else{
//Validation failed assign error and swithc cont to false
$error[$key]=$errors[$key];
$cont=false;
}
}
}
}
if($cont==true && empty($error)){
//Send mail / do insert ect
}else{
//Default to form
?>
<!doctype html>
<html>
<body>
<form action="" method="post">
<p>Name: <input type="text" name="name" value="<?=#htmlentities($name);?>"/> <?=#$error['name'];?></P>
<P>Email: <input type="text" name="email" value="<?=#htmlentities($email);?>" /> <?=#$error['email'];?></p>
<P>Phone: <input type="text" name="phone" value="<?=#htmlentities($phone);?>"/> <?=#$error['phone'];?></p><br />
<P>Subject: <input type="text" style="width:75%;" name="subject" /> <?=#$error['subject'];?></p>
<p>Comments: <?=#$error['comment'];?><br />
<textarea name="comment" rows="10" cols="50" style="width: 100%;"><?=#htmlentities($comment);?></textarea></p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
<?php
}?>

Categories