Extract Entered Data from Form (PHP) - php

I'm currently taking a course as part of my web design programs, and my final project requires creating a validating registration form. While the form validates the data correctly, I can't get it to save any data that's entered once the user submits it. I've been instructed by the course to use the 'extract' function to repopulate the form inputs, but I've had a lot of issues using this in the past as well. The following is the code for my form:
<?php
$labels = array("first_name" => "First Name*:",
"last_name" => "Last Name*:",
"company" => "Company*:",
"address" => "Address*:",
"city" => "City*:",
"province_state" => "Province/State*:",
"postal_zip" => "Postal/Zip Code*:",
"phone" => "Telephone:",
"fax" => "Fax:",
"email" => "Email Address*:",
"comments" => "Comments:");
$submit = "Submit";
?>
...
<form method="post">
<table class='form'>
<?php
foreach($labels as $label => $field)
{
if($label == 'postal_zip')
{
echo "<tr><td class='label'><label for='$label'>$field</label></td>
<td class='input'><input type='text' name='$label' maxlength='9'></td></tr>";
}
if($label == 'phone' or $label == 'fax')
{
echo "<tr><td class='label'><label for='$label'>$field</label></td>
<td class='input'><input type='text' name='$label' maxlength='14'></td></tr>";
}
if($label == 'comments')
{
echo "<tr><td class='label'><label for='$label'>$field</label></td>
<td class='input'><textarea name='$label' cols='30' rows='5'></textarea></td></tr>";
}
else
{
if($label != 'postal_zip' && $label != 'phone' && $label != 'fax' && 'comments')
{
echo "<tr><td class='label'><label for='$label'>$field</label></td>
<td class='input'><input type='text' name='$label' value='$value'></td></tr>";
}
}
echo "</tr>";
}
echo "<tr><td></td>
<td><input type='hidden' name='submitted' value='yes'>
<input type='submit' name='$submit' value='$submit'></td>";
?>
</table>
</form>
And the following is my validation code.
<?php
$message = "";
if(isset($_POST['submitted']) and $_POST['submitted'] == 'yes')
{
foreach($_POST as $field => $value)
{
if(empty($value) or !empty($value))
{
$email_patt = "/^.+#.+\\..+$/";
$name_patt = "/^[A-Za-z' -]{1,50}/";
$addr_patt = "/^[A-Za-z0-9 .,'-]{1,50}$/";
$postal_patt = "/^[A-Za-z0-9-]{1,10}$/";
$phone_patt = "/^[0-9)(xX -]{7,20}$/";
if(preg_match("/first_name/i",$field))
{
if(!preg_match($name_patt,$value))
{
$error_array[] = "Please enter a valid first name.";
}
}
if(preg_match("/last_name/i",$field))
{
if(!preg_match($name_patt,$value))
{
$error_array[] = "Please enter a valid last name.";
}
}
if(preg_match("/address/i",$field))
{
if(!preg_match($addr_patt,$value))
{
$error_array[] = "Please enter a valid address.";
}
}
if(preg_match("/company/i",$field))
{
if(!preg_match($addr_patt,$value))
{
$error_array[] = "Please enter a valid company name.";
}
}
if(preg_match("/city/i",$field))
{
if(!preg_match($addr_patt,$value))
{
$error_array[] = "Please enter a valid city.";
}
}
if(preg_match("/country/i",$field))
{
if(!preg_match($addr_patt,$value))
{
$error_array[] = "Please enter a valid address.";
}
}
if(preg_match("/postal_zip/i",$field))
{
if(!preg_match($postal_patt,$value))
{
$error_array[] = "Please enter a valid postal/zip code.";
}
}
if(preg_match("/email/i",$field))
{
if(!preg_match($email_patt,$value))
{
$error_array[] = "Please enter a valid email address.";
}
}
}
$good_data[$field] = strip_tags(trim($value));
}
if(#sizeof($error_array) >0)
{
$message = "<ul class='error'>";
foreach($error_array as $value)
{
$message .= "<li>$value</li>";
}
$message .= "</ul>";
extract($good_data);
include "contact_form.php";
exit();
}
else
{
header('location: success.html');
}
}
else
{
include "contact_form.php";
}
?>
Currently, I have all of the $_POST values put into the array $good_data, and using print_r in the validation code, I get a list of all of the fields and values entered by the user (though it does include all inputs on the page). Is there a simple way to put these values in each field?

Thanks to Dagon for the answer to my question. By adding $_POST[$field] to the value of each field, it retains the data and functions properly.

Related

PHP undefined variable when url identifier is present

I apologize for this being a bit lengthy but I wanted to show the code and not leave anything out.
The Goal: The user submits a registration form that submits the form to a database which adds the info plus a unique string to the database. Once the user submits an email is sent to the user that contains a link to a php page that has that unique string as a URL identifier at the end like so:
xyz.com/activate.php?uid=292ca78b727593baad9a
When the user clicks that link they are taken that page where they will fill out another form and when they click submit it will activate their account.
The Problem: When the user goes to the link provided they receive an error from my validation page like so:
Undefined index: variable in process.php
BUT when the user deletes the URL identifier so the URL shows as:
xyz.com/activate.php
The user does not receive an error and the validation page (process.php) works properly. I have attempted to use the identifier with a $_GET['uid'] and checking if it exists before running the code but the result was the same. I cannot find an answer when attempting to google this issue so I apologize if this has been asked before.
The Question: Why does this work without the URL identifier but not with it? I do realize the URL identifier basically does a $_REQUEST when the page first loads which is what runs the process.php. Is there a way to prevent that?
So that you guys know the code I am working with I have posted it below.
activate.php:
<?php
// validate the form.
require_once('process.php');
$validation_rules = array(
'company_name' => array(
'required' => true,
'min-length' => 2
)
);
$db_error = '';
$validate = new validator();
$validate->validate($validation_rules);
if ($validate->validate_result()) {
// the validation passed!
}
?>
<div class="bg v-100 cm-hero-activate">
<div class="v-100">
<div class="v-set v-mid">
<form class="v-mid v-bg-white <?php if(!$validate->validate_result() && $_POST || !empty($error)) { echo "shake"; } ?>" name="activation" action="" method="post">
<fieldset>
<div class="form-content">
<div id="content">
<div class="form-inner in" data-id="1" data-name="activate">
<h1>ACTIVATE YOUR ACCOUNT</h1>
<div class="form-section">
<h2>Personal Info</h2>
<?php if (!empty($db_error)) {
echo $db_error;
} ?>
<div class="field-group">
<input type="text" id="company_name" class="field required" name="company_name" value="<?php $validate->form_value('company_name'); ?>">
<label for="company_name" class="placeholder">Company Name</label>
<?php $validate->error(array('field' => 'company_name', 'display_error' => 'single')); ?>
</div>
</div>
<div class="field-bottom">
<button name="submit" data-name="activate" class="bttn btn-dark btn-hover-gloss">ACTIVATE MY ACCOUNT</button>
</div>
</div>
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
process.php:
<?php
class validator {
private $validation_rules;
private $errors = array();
private $validate_result = array();
public function validate($rules) {
$this->validation_rules = $rules;
if($this->validation_rules && $_REQUEST) {
foreach($this->validation_rules as $field => $rules) {
$result = $this->process_validation($field, $rules);
if($result == false) {
$this->validate_result[] = 0;
} elseif($result == true) {
$this->validate_result[] = 1;
}
}
}
}
public function form_value($field_name = '') {
if($this->validation_rules) {
if($_REQUEST && $_REQUEST[$field_name]) {
if(!$this->validate_result()) {
echo $_REQUEST[$field_name];
}
}
}
}
public function validate_result() {
if($this->validation_rules) {
if($_REQUEST) {
$final_result = true;
$length = count($this->validate_result);
for($i=0;$i < $length; $i++) {
if($this->validate_result[$i] == 0) {
$final_result = false;
}
}
return $final_result;
}
}
}
private function process_validation($field, $rules) {
$result = true;
$error = array();
foreach($rules as $rule => $value) {
if($rule == 'required' && $value == true) {
if(!$this->required($field, $value)) {
$error[] = "$field - required";
$result = false;
}
} elseif($rule == 'min-length') {
if(!$this->minlength($field, $value)) {
$error[] = "$field - minimun length is $value";
$result = false;
}
}
}
$this->errors[] = array($field => $error);
return $result;
}
public function error($data = '') {
if($this->validation_rules) {
if($_REQUEST) {
foreach($this->errors as $err) {
if(isset($data['field'])) {
foreach($err as $field => $field_error) {
if($data['field'] == $field) {
foreach($field_error as $error_data) {
if(isset($data['display_error']) == 'single') {
echo '<p class="error">' . $error_data . '</p>';
goto next;
} else {
echo '<p class="error">' . $error_data . '</p>';
}
}
next:
}
}
} else {
foreach($err as $field => $field_error) {
foreach($field_error as $error_data) {
if(isset($data['display_error']) == 'single') {
echo '<p class="error">' . $error_data . '</p>';
goto next1;
} else {
echo '<p class="error">' . $error_data . '</p>';
}
}
next1:
}
}
}
}
}
}
private function required($field, $value) {
if(empty($_REQUEST[$field])) {
return false;
} else {
return true;
}
}
private function minlength($field, $value) {
if(strlen($_REQUEST[$field]) < $value) {
return false;
} else {
return true;
}
}
?>
EDIT: it seems that the error is happening on the if statement in the min-length function: if(strlen($_REQUEST[$field]) < $value)
EDIT 2: This may also be of some use. The textbox is being filled with this: <br /><font size='1'><table class='xdebug-error xe-notice' dir='ltr' border='1' cellspacing='0' cellpadding='1'><tr><th align='left' bgcolor='#f57900' colspan=
and underneath that I receive this error: Notice: Undefined index: company_name in C:\...\process.php on line 25 Call Stack #TimeMemoryFunctionLocation 10.0005369632{main}( )...\activate.php:0 20.0029403928validator->form_value( )...\activate.php:80 ">
Your $field_name doesn't exist in the $_REQUEST array which is why you are getting your undefined index error.
You are not checking if the value is set - just accessing it via $_REQUEST[$field_name] in your if statement.
Change
public function form_value($field_name = '') {
if($this->validation_rules) {
if($_REQUEST && $_REQUEST[$field_name]) {
if(!$this->validate_result()) {
echo $_REQUEST[$field_name];
}
}
}
}
To
public function form_value($field_name = '') {
if($this->validation_rules) {
if($_REQUEST && isset($_REQUEST[$field_name])) {
if(!$this->validate_result()) {
echo $_REQUEST[$field_name];
}
}
}
}
Unrelated Tips.
Aim for cleaner - and more concise readable code.
$input = [
'name' => 'Matthew',
];
$rules = [
'name' => 'required|string',
];
$v = (new Validator())->validate($input, $rules);
if ($v->fails()) {
// Do something with $v->errors();
return;
}
// Do something with validated input
Try and avoid using else or elseif wherever possible. This can be achieved by looking for the negative first, and exiting early. Try not to have too many levels of nesting. It makes your code extremely difficult to read and increases cyclomatic complexity.
Also - take a look at an MVC framework which should help you to structure your code. A good start would be something like Laravel https://laravel.com/ there are good tutorials on https://laracasts.com/
You are getting this error because you have logic like
if($this->validation_rules && $_REQUEST) {
In PHP, an empty array is falsy and a non-empty one, truthy.
$_REQUEST is a combination of $_GET, $_POST and $_COOKIE.
When you add the uid query parameter, $_REQUEST will not be empty and therefore not falsy and your validator will attempt to run but without the expected POST data (such as company_name).
If you're only wanting to validate POST data, you should only be inspecting $_POST.
See Gravy's answer for safer ways to check for the existence of array keys.

Calling function to validate post array php

I am trying to get an post array validated by php, Scenario 2 works , Scenario 1 doesn't - when calling the function inside a loop , Please Help
Scenario 1
// Trying to call the function in the loop
<form action="new_signup_form_upload.php" method="POST">
Email 1 <input type = "text" name = "email[newsignup_email1]">
Email 2 <input type = "text" name = "email[newsignup_email2]">
<input type="submit" id= "submit" name= "submit">
function validate_email(){
if ($value == "") {
echo $nameErr = '<div id = "error_message_div">Name is required</div>';
return false;
}
else{
if(!filter_var($value, FILTER_VALIDATE_EMAIL)) {
echo $emailErr = '<div id = "error_message_div">Invalid email format</div>';
return false;
}
}
}
foreach($_POST[email] as $key => $value){
validate_email();
}
Scenario 2
// The difference here is am writing the function when inside the loop
<form action="new_signup_form_upload.php" method="POST">
Email 1 <input type = "text" name = "email[newsignup_email1]">
Email 2 <input type = "text" name = "email[newsignup_email2]">
<input type="submit" id= "submit" name= "submit">
foreach($_POST[email] as $key => $value){
if ($value == "") {
echo $nameErr = '<div id = "error_message_div">Name is required</div>';
return false;
}
else{
if(!filter_var($value, FILTER_VALIDATE_EMAIL)) {
echo $emailErr = '<div id = "error_message_div">Invalid email format</div>';
return false;
}
}
}
the function validate_email does not have any access to outside variables (except the really really global ones). Besides a lot of other objections to the code.. you should pass the $value in your foreach loop
function validate_email($value){
if ($value == "") {
echo $nameErr = '<div id = "error_message_div">Name is required</div>';
return false;
}
else{
if(!filter_var($value, FILTER_VALIDATE_EMAIL)) {
echo $emailErr = '<div id = "error_message_div">Invalid email format</div>';
return false;
}
}
}
foreach($_POST[email] as $key => $value){
validate_email($value);
}

Function to Check if POST is empty and add custom error messages

I have some code to check an empty post like this:
foreach($_POST as $key => $value)
{
if (empty($_POST[$key]))
{
$errors[] = "$key" . "is empty.";
}
}
how can i add some custom messages because using $key + is empty isn't good enough for me. i want to display custom messages for every post. maybe some function like validate($name, Please enter your name, required). but i don't have a clue how to do it, can anyone can provide me some method i can try?
Since you want a custom message depending on the key, you should just use a switch.
$errors = array();
foreach($_POST as $key => $value)
{
if (empty($value))
{
switch($key) {
case 'name':
$errors[] = "The name is empty.";
break;
case 'age':
$errors[] = "The age is empty.";
break;
default:
$errors[] = $key . " is empty.";
}
}
}
* Edit *
If you want to do special treatment according to the key, and use a function :
$errors = array();
foreach($_POST as $key => $value)
{
$result = validate($key, $value);
if (!empty($result)) {
$errors[] = $result;
}
}
function validate($key, $value) {
if ($key == 'name' && empty($value)) {
return 'You must enter your name';
}
elseif ($key == 'age' && empty($value)) {
return 'You must enter your date of birth';
}
elseif ($key == 'email' && filter_var($value, FILTER_VALIDATE_EMAIL) === false) {
return 'Your email is incorrect';
}
return '';
}
Check for Form Validation scripts/tutorials with PHP.
Here are some quick findings:
Using modular approach: http://www.sitepoint.com/form-validation-with-php/
Using class based (OOP) approach: http://www.html-form-guide.com/php-form/php-form-validation.html
if you want to use same approach, then use this
foreach($_POST as $key => $value)
{
if (empty($_POST[$key]))
{
$errors[] = getValidationMessage($key);
}
}
function getValidationMessage($key){
if($key == "user_name")
return "please enter user name.";
else if ($key == "date_of_birth")
return "please enter you date of birth";
//and so on,
//based on param names in your html-forms
}
Something like this?
foreach ($_POST as $k => $v) {
$errors[] = validate($k);
}
function validate($key) {
if(empty($_POST[$key])) {
switch ($key) {
case 'name':
$message = "Name is empty";
break;
case 'email':
$message = "fill in your email address";
break;
default:
$message = $key." is empty";
break;
}
return $message;
}
return false;
}

PHP Validation form submit

How do you stop an email being sent to you before the form is fully completed. Currently when submit is clicked even though there are validation errors present that have been picked up via the PHP checks that I have in place:
Code:
if (isset($_POST['submitButton'])) {
$fullName = $_POST['fullName'];
$myGender = isset($_POST['myGender']) ? $_POST['myGender'] : '';
$email = $_POST['email'];
$age = $_POST['age'];
$myDate = isset($_POST['myDate']) ? $_POST['myDate'] : '';
$streetNum = $_POST['streetNum'];
$streetName = $_POST['streetName'];
$city = $_POST['city'];
$state = $_POST['state'];
$postCode = $_POST['postCode'];
$movie = $_POST['movie'];
//You need to se the $var
if (empty($fullName))
{
$errorfullName .= 'Please Enter Your Name';
}
if (!ctype_alpha(str_replace(array(" ", "-"), "",$fullName))) {
$errorfullName .= 'Your name should contain alpha characters only.';
}
if (strlen($fullName) < 3 OR strlen($fullName) > 40) {
$errorfullName .= 'First name should be within 3-40 characters long.';
}
/* Check Gender) */
if ($myGender != 'male' && $myGender != 'female') {
$errormyGender .= 'Please select your gender.';
}
/* Check Email */
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$erroremail .= 'Enter a valid email address.';
}
/* Age */
if (intval($age) == '') {
$errorage .= 'Please enter your current age';
}
if (intval($age) < 3 OR intval($age) > 200){
$errorage .= 'Age must be less than 200 years';
}
if(intval($age) == "/^[0-9]$/" ){
$errorage .= 'Must be numeric numbers';
}
/* check date using explode (breaks a string into an array.)if day is not 1-31, throw error*/
if(empty($myDate))
{
$errormyDate.= 'Please enter a current date';
}
$date_arr = explode ("-", $myDate);
$dateSplit = array_slice($date_arr, 0,1);
$dateYear = current($dateSplit);
if($dateYear > date('Y'))
{
$errormyDate .= 'Sorry your not born in the future';
}
/* Check Address House Number if its not numeric, throw error */
if (intval($streetNum) == '') {
$errorstreetNum .= 'Please add street Number';
}
/* Street Name */
if (strlen($streetName) < 3 OR strlen($streetName) > 200) {
$errorstreetName .= 'Street must be filled out and within 200 characters';
}
/*City Name */
if (strlen($city) < 3 OR strlen($city) > 200) {
$errorcity .= 'City must be filled out and within 200 characters';
}
/*State Name */
if (strlen($state) < 3 OR strlen($state) > 200) {
$errorstate .= 'State must be filled out and within 200 characters';
}
/* Check postCode */
if(intval($postCode) == "/^[0-9]$/" ){
$errorpostCode .= 'Post Code must be numeric numbers';
}
/* Check movie selection */
if (trim($movie) === "select") {
$errormovie .= 'Please select a favourite movie';
}
if ($fullName, $myGender, $email, $age, $myDate, $streetNum, $streetName, $city, $state, $postCode, $movie, == " "){
echo '$errorsuccess .= 'Please complete all sections of the form'';
}
else {
$success = "Thank you for submitting your form; We will be in contact soon";
//send mail
$to = "#yahoo.co.nz";
$subject = "Php form data";
$message = "<p>".$fullName."</p><p>".$myGender."</p><p>".$email."</p><p>".$age."</p><p>".$myDate."</p><p>".$streetNum."</p><p>".$streetName."</p><p>".$city."</p><p>".$state."</p><p>".$postCode."</p><p>".$movie."</p>";
$from = "#yahoo.co.nz";
mail($to,$subject,$message);
}
}
The reason being is that you even though you have several validations completed in the above, none of them are later checked to see if they failed/passed, your only sanity check is here:
if ($fullName, $myGender, $email, $age, $myDate, $streetNum, $streetName, $city, $state, $postCode, $movie, == " "){
Which its self is pretty useless all together, by the way.
A simpler way for this would be to first create an array to hold all the errors.
$errors = array();
Then when you do your individual checks, make them a key, for example:
if (empty($fullName))
{
$errors['fullname'] .= 'Please Enter Your Name';
}
And
if (intval($age) == '') {
$errors['age'] .= ' Please enter your current age.';
}
if (intval($age) < 3 OR intval($age) > 200){
$errors['age'] .= ' Age must be less than 200 years.';
}
if(intval($age) == "/^[0-9]$/" ){
$errors['age'] .= ' Must be numeric numbers.';
}
Then later you can do:
if($errors){
echo 'There are errors in the form. Please observe each of the errors and try again.'. PHP_EOL;
foreach($errors as $idx => $error){
echo ucfirst($idx). ': ' .$error;
}
}
Set something like $err to false at the beginning of the code. Set it to true when an error is detected. (Even if it's already true; just setting it is easier than checking.)
Then, you can condition the final result on $err.
It looks like that in order to send the email, you only need to have a value for each of your input fields (from $fullName to $movie).
Where you are validating the form (for example, when you use if (empty($fullName))..., the error that is produced if the form isn't filled out correctly always differs. Unless you have some kind of reason for this, I would just stick to a generic error variable of $formerror.
Then in the final section of your code, where you use if($fullName...$movie == ''), you could change this to if($fullName...$movie === '' AND !empty($formerror)) so that if any errors were picked up during the validating of the form, you would be able to echo $formerror and if not, the email would send.

php form doesnt submit one of the fields

i have bought a template that have built in contact form
problem is that it submits every thing except "company" name
i messed around with it but cant get to work it.
if you can point me to some solution i would be greatful
thanks in advance
this is php script
if(!$_POST) exit;
$email = $_POST['email'];
//$error[] = preg_match('/\b[A-Z0-9._%-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\b/i', $_POST['email']) ? '' : 'INVALID EMAIL ADDRESS';
if(!eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*" ."#"."([a-z0-9]+([\.-][a-z0-9]+)*)+"."\\.[a-z]{2,}"."$",$email )){
$error.="Invalid email address entered";
$errors=1;
}
if($errors==1) echo $error;
else{
$values = array ('name','email','message');
$required = array('name','email','message');
$your_email = "--------#gmail.com";
$email_subject = "New Message: ".$_POST['subject'];
$email_content = "new message:\n";
foreach($values as $key => $value){
if(in_array($value,$required)){
if ($key != 'subject' && $key != 'company') {
if( empty($_POST[$value]) ) { echo 'Please fill in all required fields, marked with *'; exit; }
}
$email_content .= $value.': '.$_POST[$value]."\n";
}
}
if(#mail($your_email,$email_subject,$email_content)) {
echo 'Thanks for your message, will contact you soon.';
} else {
echo 'ERROR!';
}
}
$values = array ('name','email','message');
Add 'company' to this list in the PHP script.
Also, I would modify the foreach loop to look like this, to get the intended functionality:
foreach($values as $key => $value)
{
if(in_array($value,$required))
{
if(empty($_POST[$value]))
{
echo 'Please fill in all required fields, marked with *';
exit;
}
}
$email_content .= $value.': '.$_POST[$value]."\n";
}
This way, fields that aren't in the $required array are still added to the email if they exist - they just don't have to pass the empty check.
The problem is this line:
$email_content .= $value.': '.$_POST[$value]."\n";
Is never reached unless this line:
if (in_array($value,$required)) {
... is satisfied. This means, only fields listed in $required are going to be appended to the email. If that is OK, then simply change these lines:
$required = array('name','email','message');
$values = array ('name','email','message');
To read:
$required = array ('name','email','message','company');
$values = array ('name','email','message','company');
If that is NOT ok, change this:
foreach ($values as $key => $value) {
if (in_array($value,$required)) {
if ($key != 'subject' && $key != 'company') {
if (empty($_POST[$value])) {
echo 'Please fill in all required fields, marked with *';
exit;
}
}
$email_content .= $value.': '.$_POST[$value]."\n";
}
}
To look like this:
foreach ($values as $key => $value) {
if (in_array($value,$required)) {
if ($key != 'subject' && $key != 'company') {
if (empty($_POST[$value])) {
echo 'Please fill in all required fields, marked with *';
exit;
}
}
}
$email_content .= $value.': '.$_POST[$value]."\n";
}
Then you can take company out of $required, but leave it in $values. I suspect the template worked fine when you started because all fields were required.
If it still does not work, please change this (up top):
if(!$_POST) exit;
To look like this:
if(!$_POST) exit;
print_r($_POST);
... and paste the additional output in your question.
Also, consider buying templates from another vendor :)

Categories