Check if array elements are empty - php

I have a simple PHP form that I'd like to improve validation to help fight empty form submissions from bots.
I have the following array that houses input names from another page.
$expected = array('Project-Inquiry','Name','Company-Name','Phone-Number','Email');
I'd like to verify that these elements, in fact, do contain content, as they're already verified with JS on the previous page. JS is only good when it's enabled, so I'd like to add an extra layer of validation here for when it's disabled.
I tried the following:
$expected = array_filter($expected);
if (!empty($expected)) {
// Do Something
}
And I have also tried the following:
$error = false;
foreach($expected as $field) {
if (empty($_POST[$field])) {
$error = true;
}
}
if ($error) {
// Do Something
}
I seem to be falling short. Any suggestions?

If you want to fight against bots
Create a hidden input that human doesn't see and bots will fill it. You need to check that input before doing anything. If that input filled, it means that form sent by bot not human.
Create a session with current time when you are showing form, when post happening check the time difference. if it is less than 3 sec it's a bot.
use captcha system.
If you want to validate inputs
Don't do validation like what you did on your question. You should try to validate each one of them with proper validation method. for example how you should validate email is completely different from name.
for example do this for email:
$email = (isset($_POST['email']) && is_string($_POST['email']))? trim($_POST['email']) : '';
$email_error = (filter_var($email,FILTER_VALIDATE_EMAIL))? true : false;
for name is different:
$name = (isset($_POST['name']) && is_string($_POST['name']))? trim($_POST['name']) : '';
$name_error = (strlen($name)>20 || strlen($name)<3)? true : false;
You can add more filter to my examples.

Have you considered about using a library to validate?
I recommend you to use https://laravel.com/docs/5.5/validation, so you can validate more complex rules also, and it is very clear.

Let your expected data be array be
$expected = ['name', 'email', 'mobile'];
let form post values be $_POST
foreach($_POST as $key => $value) {
if (empty($value) && in_array($key, $expected)) {
if ($value=='') {
echo $key. ' is should not be empty'."<br/>";
}
}
}
you can get result as expected
HTML FORM
<form action="" method="post">
Name <input type="text" name="name"><br>
email <input type="text" name="email"><br>
mobile<input type="text" name="mobile">
<input type="submit" value="Submit">
</form>

Related

Multiple the same forms and POST method?

I have multiple instances of the same form (name / email / message fields) on one page. They all share one class ('.contact-form') and different (dynamically generated IDs).
I validate them using jQuery Tools Validator (it's not relevant though as I have no problems with this at all):
$(".contact-form").validator();
The problem lies in my sendmail.php file I suppose, that's how I get all POST values & validate them:
//grab the fields
$address = trim($_POST['address']);
$title = trim($_POST['title']);
$message = $_POST['message'];
//check if empty
if(empty($name) || empty($title) || empty($message)) {
$wrong = true;
}
if($wrong) {
http_response_code(400);
} else {
// do stuff
http_response_code(200);
}
Now, the issues I'm facing are:
I can't send any other forms excepting the very first on the page, for the rest (even if they're properly filled) I'm getting this error:
Notice: Undefined index: address in mysitesaddress on line 3
after I send the first form - the other forms doesn't act like expected - they are getting through even if all fields are left empty (validator displays errors on front end but then fires "success" after a second because sendmail.php returns "200 OK".
Any ideas how to fix it / check every form instead of just the first one / clear POST data after sending? I'm sure there's an easy way to do that in PHP, I'm not that familiar with that language (mostly a front-end guy) so any help would be much appreciated.
Thank you!
(I've been Googling for an answer for a while now, but looks like "POST" is a tricky name and I'm getting Wordpress/blogs/forums related stuff mostly...)
[update]
Here's the HTML code of each form:
<div class="wrapper">
<form class="contact-form" action="sendmail.php" method="post" novalidate="novalidate">
<input name="title" type="text" required="required" />
<input name="address" type="email" required="required" />
<textarea name="message" required="required" ></textarea>
<input type="Submit" value="Submit" />
</form>
<div class="sucess">
Success message that replaces form ^.
</div>
</div>
The notice implies the 'address' key does not exist.
You should check if the indexes in the $_POST variables are set/exist, e.g. using the PHP isset() function.
This could be caused because you aren't sending the address in every form, just in the first or something like that.
Sample code on how you could use isset to check:
if ( isset($_POST['address']) ) {
//only set $address to the $_POST value if it is set
$address = trim($_POST['address']);
}
I can't see your HTML form code, but I'm guessing your form tag looks like this
<form action="sendmail.php" method="post">
This will take all the fields from the form that was submitted and send them via $_POST to your sendmail.php. After you process the data (edwardmp gave a great tip for making sure the data was there before trying to assign the variables), you would then redirect the page to some type of success landing or back to the original form page. The method I've been using to do this is:
if($wrong) {
$error = "Please check your entry and try again.";
header("Location: http://example.com/formpage.html?error=" . htmlencode($error),true,303);
exit();
} else {
// do stuff
$msg = "Your form was successfully submitted.";
header("Location: http://example.com/formpage.html?msg=" . htmlencode($msg),true,303);
exit();
}
This design makes it so the $_POST data is cleared by reloading the page, and allows you to send messages back to the originating page which you would display through $_GET['msg'], or $_GET['error']. This should stop the forms from submitting erroneously.

Need type="text" input fields to display previously-POST'd entries if errors occur

I've probably not explained what I"m trying to do in the title very well, so here goes:
I've got a HTML entry form, in a .php file. That entry form when submitted files a POST operation. That POST operation has code to check field input, similar to this:
<?php
...
if ($_POST["submitted"] == 1) {
//"submitted" is a hidden field with value '1' in the form
$isvalid = 1; // Inits to 1, changes to 0 if something fails checks.
$field1 = $_POST["field1"];
$field2 = $_POST["field2"];
...
/*
Checks for validation on each field go here,
but are not relevant to this question here.
*/
}
if ($isvalid == 1) {
// Send email
} else { ?>
<!-- Print form, and error msg. -->
...
<input name="field1" type="text" id="field1" size="32" class="stylingclass">
...
So the above is example code, but here's the real question: How can I get any of the text input fields in my form, when submitted and an error occurred, to automatically contain the previous values that were entered, so that the user can correct the entries accordingly, based on whatever constraints I've set?
You can set the value parameter using a basic ternary operator:
<input name="field1" type="text" id="field1" value="<?php echo isset($_POST["field1"]) ? $_POST["field1"] : ''; ?>" size="32" class="stylingclass">
Note that the ternary operator is used here to prevent an error if there is no index of the specified field in the $_POST array
Just add value="<?=$_POST['field1']?>" (assuming PHP 5.4, use <?php echo $_POST['field1'] ?> otherwise)

How to make one field required only if another field is used

I have a form where users can enter the names and emails addresses of colleagues. They are not required to enter anything. However if a name is entered then the email address is required.
<form>
1st name <input type="text" name="name_1" value"" />
1st email <input type="text" name="email_1" value"" />
2nd name <input type="text" name="name_2" value""/>
2nd email <input type="text" name="email_2" value""/>
</form>
I can already make certain fields required using the function below. I think I could use an if else statement to check if the 1st name had a value then make the 1st email required. However the form has twenty potential name / email pairs.
What i'm after is advice about the sort of thing I should be trying to do this rather than a complete solution. I appriciate this a bit of a vague question but I'm very new to PHP and am having difficulty searching for a solution.
function check_required_fields($required_array) {
$field_errors = array();
foreach($required_array as $fieldname) {
if (!isset($_POST[$fieldname]) || (empty($_POST[$fieldname]) && !is_numeric($_POST[$fieldname]))) {
$field_errors[] = $fieldname;
}
}
return $field_errors;
}
As long as you are consistent with naming your fields like name_1, you can extract the number from the array keys with substring operations after _ and look for a comparable value in email_.
foreach ($_POST as $key => $value) {
// If it is a name field and isn't empty
if (strpos($key, 'name_') === 0 && !empty($_POST[$key])) {
// The email field is email_ and the number (which comes after the 5th character in name_num)
$namenumber = substr($key, 5);
$emailfield = 'email_' . $namenumber;
// Append the email requirement onto $field_errors if it's empty in $_POST
if (empty($_POST[$emailfield])) {
$field_errors[] = $emailfield;
}
}
}

How do I create a server-side form submission script that has client-side characteristics?

I'm working in PHP to build a form. I know how to display the form and then take submitted values from the $_POST variable, and I know how to validate those variables and display a "Thank You" or an "Error" page depending on the input.
What I don't know how to do, though, is create a client-side-like system wherein despite having my users hit a "back" button a separate screen I can then take the information I gathered from the first submission and display dynamic error messages like "Please provide a valid email address" or "First name is a required field" next to the fields that were entered incorrectly. I'd also like to retrieve any previously submitted data that was valid and have it populate in the form so users don't get frustrated by losing everything they entered.
What is the right approach to accomplishing something like this in PHP? I originally thought if I could pass back an array of error messages with an input type="hidden" tag I could then pull my values and display messages dynamically with PHP, but I keep getting stuck in that approach.
You could add the errors a php session, but this creates issues for users who have multiple browser tabs open.
My preferred method is to have the form submit to the same page and put the errors directly on that page so the user does not have to click the back button. That way you can highlight the fields directly in the form (make the background or outline red or something similar.)
<input type="text"
<?php (empty($_POST['field']?'style="backgroung-color: red;"':''))?>
name="field" value="<?php echo $_POST['field']?>" />
You can put <input type="text" name="field" value="<?php echo $_POST['field']?>" /> to get the old value.
Because the web is, by definition, stateless, there is no really good way to track what the user does when they hit the back button. There are hacks that work using a hidden iframe, but that is way more trouble that what you are looking for.
Don't mix client logic with server logic. The exact same script can output the form and take it's input. In case input successfully validates, it goes on. If not, it will display the form again, this time with error messages and the already-entered data.
Next time the user submits the form, validation starts again until it passes successfully.
So you extend the form with input values and error messages in the first place, but you only display them if flagged/set.
This can be done just with additional variables next to $_POST - or if you like it - by using a complete form abstraction from a framework, like zend framework (which might be overhead for what you like to do) or just with a library/component like the popular HTML_QuickForm2.
Edit:
This is some very bare code to demonstrate the overall methodology, if you use a library it is much nicer (and you don't have to code it instead you can concentrate on the actual form like the definition on top). This code is more for reading and understanding the flow than for using, I quickly typed it so it (most certainly has) syntax errors and it's not feature complete for a full blown form. This one has only one email field and is even missing the submit button:
/* setup the request */
$request->isSubmit = isset($_POST['submit']);
/* define the form */
$form->fields = array
(
'email' => array
(
'validate' => function($value) {return filter_var($value, FILTER_VALIDATE_EMAIL);},
'output' => function($value, $name) {return sprintf('<input type="text" value="%s" id="%s">', htmlspecialchars($value), htmlspecialchars($name)},
'default' => 'info#example.com',
),
);
/**
* Import form data from post request
*
* #return array data with keys as field names and values as the input strings
* or default form values.
*/
function get_form_post_data($form, $request)
{
$data = array();
foreach($form->fields as $name => $field)
{
$data[$name] = $field->default;
if ($request->isSubmit && isset($_POST[$name]))
{
$data[$name] = $_POST[$name];
}
}
return $data;
}
/**
* Validate form data
*/
function validate_form_data($form, $data)
{
foreach($form->fields as $name => $field)
{
$value = $data[$name];
$valid = $field['validate']($value);
if (!$valid)
{
$form->errors[$name] = true;
}
}
}
function display_form($form, $data)
{
foreach($form->fields as $name => $field)
{
$value = isset($data[$name]) ? $data[$name] : '';
$hasError = isset($form->errors[$name]);
$input = $field['output']($name, $value);
$mask = '%s';
if ($hasError)
{
$mask = '<div class="error"><div class="message">Please Check:</div>%s</div>';
}
printf($mask, $input);
}
}
// give it a run:
# populate form with default values -or- with submitted values:
$form->data = get_form_post_data($form, $request);
# validate form if there is actually a submit:
if ($request->isSubmit)
{
validate_form_data($form, $form->data);
}
# finally display the form (that can be within your HTML/template part), works like echo:
display_form($form, $form->data)
Use the form to submit to the same page, and if the form validates, use a header to redirect the user into the thank you page.
header("Location: thank-you.php");
If the form fails validation, you could easily display all the errors on the same page.

Retaining values in forms fields when validation of data fails

I am having problems figuring out how to retain users data when the validation fails. I am somewhat new to PHP so I might be making some huge mistakes in my logic.
Currently if the validation fails all the fields are wiped clean and $_Post data is also gone.
Here is some code assuming the user enters an invalid email I want the Name field to be retained. This code is not working.
<?php
if($_POST['doSubmit'] == 'Submit') {
$usr_name = $data['Name'];
$usr_email = $data['Email'];
if (isEmail($usr_email)==FALSE){
$err = "Email is invalid.");
header("Location: index.php?msg=$err");
exit();
}
//do whatever with data
}
if (isset($_GET['msg'])) {
$msg = mysql_real_escape_string($_GET['msg']);
echo "<div class=\"msg\">$msg</div><hr />";
}
if (isset ($_POST['Name'])){
$reusername = $_POST['Name'];}
else{$reusername = "NOTHING";}//to test
?>
<form action="index.php" method="post" >
<input name="UserName" type="text" size="30" value="<?echo $reusername;?>">
<input name="Email" type="text" size="30">
<input name="doSubmit" type="submit" value="submit">
</form>
}
You can use AJAX to submit your form data to your PHP script and have it return JSON data that specifies whether the validation was successful or not. That way, your fields won't be wiped clean.
Another way is to send back the recorded parameters to the posting page, and in the posting page, populate the fields using PHP.
However, I think the first solution is better.
UPDATE
The edit makes your code clearer and so I noticed something. Your input field is called UserName in the HTML, but you are referring to Name in PHP. That's probably why it's not working. Is your field always being filled with the value NOTHING? Make sure the name of the input field and the subscript you are using in $_POST are the same.
Also, there's no need to redirect to another page (using header) if you have an error. Maintain an $errors array or variable to print error messages in the same page. But like I mentioned before, it's probably better to use the JSON approach since then you can separate your view layer (the html) from the PHP (controller layer). So you'd put your HTML in one file, and your PHP in another file.
EDIT:
Vivin had commented that my assumption regarding the header was incorrect and he was right in that. Further more it looks like what the OP is doing is essentially what i layed out below albeit in a less structured fashion. Further Vivin - caught what is likely the actual problem here - the html name and the array key $_POST do not match.
Its wiped clean because you are using header to redirect to another page. Typicaly you would have a single page that validates the data and if ok does something with it and returns a success view of some sort, or that returns an error view directly showing the form again. By using header youre actually redirecting the browser to another page (ie. starting up an entirely new request).
For example:
// myform.php
if(strtolower($_SERVER['REQUEST_METHOD']) == 'get')
{
ob_start();
include('form.inc.php'); // we load the actual view - the html/php file
$content = ob_get_clean();
print $content; // we print the contents of the view to the browser
exit;
}
elseif(strtolower($_SERVER['REQUEST_METHOD']) == 'post')
{
$form = santize($_POST); // clean up the input... htmlentities, date format filters, etc..
if($data = is_valid($form))
{
process_data($data); // this would insert it in the db, or email it, etc..
}
else
{
$errors = get_errors(); // this would get our error messages associated with each form field indexed by the same key as $form
ob_start();
include('form.inc.php'); // we load the actual view - the html/php file
$content = ob_get_clean();
print $content; // we print the contents of the view to the browser
exit;
}
}
so this assumes that your form.inc.php always has the output of error messages coded into it - it just doesnt display them. So in this file you might see something like:
<fieldset>
<label for="item_1">
<?php echo isset($error['item_1']) ? $error['item_1'] : null; ?>
Item 1: <input id="item_1" value="<?php echo $form['item_1'] ?>" />
</label>
</fieldset>
Could do something similar to if failed then value=$_POST['value']
But vivin's answer is best. I don't know much about AJAX and wouldn't be able to manage that.
Ok, firstly header("Location: index.php?msg=$err"); is not really required. It's best practice not to redirect like this on error, but display errors on the same page. Also, redirecting like this means you lose all of the post data in the form so you can never print it back into the inputs.
What you need to do is this:
<input name="Email" type="text" size="30" value="<?php print (!$err && $usr_email ? htmlentities($usr_email, ENT_QUOTES) : '') ?>">
Here I'm checking whether any errors exist, then whether the $usr_email variable is set. If both these conditions are matched the post data is printed in the value attribute of the field.
The reason I'm using the function htmlentities() is because otherwise a user can inject malicious code into the page.
You appear to be processing the post on the same page as your form. This is an OK way to do things and it means you're nearly there. All you have to do is redirect if your validation is successful but not if it fails. Like this
<?php
if( isset( $_POST['number'] ) ) {
$number = $_POST['number'];
// validate
if( $number < 10 ) {
// process it and then;
header('Location: success_page.php');
} else {
$err = 'Your number is too big';
}
} else {
$number = '';
$err = '';
}
?>
<form method="POST">
Enter a number less than 10<br/>
<?php echo $err ?><br/>
<input name="number" value="<?php echo $number ?>"><br/>
<input type="submit">
</form>

Categories