Friendlier form validation with error logging on all inputs - php

I am tying to refine how my application handles drawing forms and validating their inputs. In particular, I want the option of testing ALL inputs for validation instead of just returning on the first error I find! I'd like to accomplish a structure like this...
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
if (check_field($_POST['name']))
{
$form_errors['name'] = 'Name is invalid';
}
if (check_field($_POST['email']))
{
$form_errors['email'] = 'E-mail is invalid';
}
if (count($form_errors) == 0)
{
// All validations succeeded
// Continue processing the form
// Show confirmation for user
// DO NOT REDRAW THE FORM!!!
}
else
{
// Somehow jump to the SHOW_FORM below
}
}
elseif (SHOW_FORM)
{
// Show ALL errors we have collected, if any
print_r($form_errors);
/*
* A block of code that draws the form!
* A block of code that draws the form!
* A block of code that draws the form!
*/
}
else
{
// Show a list of records to edit
}
I have been accomplishing this with functions up until now. I have 1.) a function that draws the form and prints the contents of the $form_errors array if any and 2.) a function that validates the form inputs on submission. If the validation function returns false (which it does if any errors are found), the user lands back on the form with all of their errors on display.
Writing a pair of functions for every new form has become cumbersome and leads to a lot of repeat code. If possible, I'd like to abandon this practice and just have my parent page validate form inputs, but default to simply drawing the form. I would like assistance in structuring the page in this way.

Here's some ideas:
Put your forms into their own files with nothing but the html & code to display errors only (this is called a View).
Post to a page that handles the post (this is called a Controller).
In the page that handles the post, only validate using re-usable functions that you have included from another file. For example the validation function might look like this: validate_email($_POST['email']); or validate($_POST['email'], 'email');, or validate($_POST, ['email' => 'email']);

Related

How to put IF condition for input field in a contact form (PHP, CODEIGNITER)

PHP Controller:
$this->form_validation->set_rules('phone', $this->language->get_text('phone', 'global'), 'max_length[0]');
I need to put an IF condition for the above line code to return this:
if (The_Above_Line_Code is NOT empty)
{
$this->output->set_status_header(400);
exit;
}
So, if the input field don't contain characters it's OK and the contact form to work properly, but if contain characters, then should return a blank page (set_status_header(400)).
PS: It's a way to combat spam in contact form.
$this->form_validation->set_rules('phone', $this->language->get_text('phone', 'global'), 'max_length[0]|numeric');
If it's not a number then form validation fails. I don't see the logic in serving a 400.
https://www.codeigniter.com/userguide3/libraries/form_validation.html?highlight=form%20validate#rule-reference
Update
After understanding your reasoning better you can simply do this:
if (!empty($this->input->post('phone'))) {
show_404(); // sets header + exits
}
You can even use show_404() (CI function) as a way to log the error: show_404('bot detected', true);.

How to implement a form validation page that also displays the result?

Currently, I am having one page that display query options and does the form validation and another page that process the query and shows the result if validation is successful. I am trying to combine these two pages together such that the user would not need to go back and forth the two pages every time to make some query changes.
The structure of the two page process is as follows:
**Validation Page**
if (post detected)
{
validate input
if (no error)
{
record query options
redirect to results page
exit
}
else
{
output error message
}
}
display form
**Results Page**
if (query options are set)
{
process query
display results
}
else
{
redirect to validation page
}
I have seen the concept being implemented simply in search engine pages where the search box and the results are in one page. I am looking to implement something like that using the POST method with a form containing both select and input boxes.
You can just set the form action to itself (or leave it blank along the lines of action = "" and it will point to itself anyhow, then use a simple check to see whether any form data has been submitted to determine if you should show the empty page or the search results:
if(isset($_REQUEST['searchStuffs']) // Not sure if you are GET or POST'ing
{
if(!empty($_REQUEST['searchStuffs'])
{
// do stuff here to get the form result, then display it
}
else
{
// The form was submitted empty, so show an error
}
}
else
{
// Display the normal search/form page as it hasn't been sent.
}
You can also use the following approach (which I would probably use though it is some extra work):
$searchBool=false;
if(isset($_REQUEST['searchStuffs']) // Not sure if you are GET or POST'ing
{
if(!empty($_REQUEST['searchStuffs'])
{
if(...)// valid search criteria
{
$searchBool=true;
// Do stuff to get search results
$searchResults='some output or data';
}
}
}
// Echo normal input form
if($searchBool)
{
echo $searchResults;
}

PHP OOP message keeps displaying on page refresh

I have a relatively simple class which deletes a post:
function delete_post($postid, $reason){
//Stuff to delete post
$this->delete_response = 'Thanks, your course has been removed.';
}
This function is called at the top of a page with a form on. If the form is submitted, the same page checks the POST[] and carries out the function, like so:
if(!empty($_POST['removecourse'])){
$courseManager->delete_post($_POST['courseid'], $_POST['cancel-reason']);
echo $courseManager->delete_response;
};
So my problem is... when I refresh the page, the message keeps displaying. I know this is because I am re-submitting the form, and because there is no such P/R/G pattern going on, but as i am new to OOP, im wondering if im doing this the right way, or if anyone could suggest a way similar to PRG or something?
Add an if that test if somthing changed, like mysql_affected_rows
function delete_post($postid, $reason)
{
//Stuff to delete post
if(mysql_affected_rows())
{
$this->delete_response = 'Thanks, your course has been removed.';
}
}

Zend Framework - Validating contents of upload (secondary validation)

I'm currently having users upload a MS Word Document where I am checking a version within the XML. The controller currently checks isValid() and then hits a library that does the parsing and extraction (since word is an archive). Now since it's technically "valid" already, I need to check the validity again through the library. What is the best course of action in Zend Framework for this?
Cheers from Kohana Land ;)
I think I understand what you are looking for.
You are currently calling is valid against the form, your file passes the form validation (correct size, extension ...) now you need to unpack the file and validate the contents.
I'm going to assume you already have the code to validate the contents and just want to understand how that might be used in the controller.'
public function anyAction() {
$form = new Form();
//test for $_POST
if ($this->getRequest()->isPost(){
//Test form for validity
if ($form->isValid($this->getRequest()->getPost()){
//will receive file upload (unless disabled in element) and filter form values,
//based on filters attached to the elements.
$data = $form->getValues();
//placeholder for whatever code is required to validate contents of file
$validateFile = new MyFileValidator();
//test for valid file contents
if ($validateFile->isValid($data['file']){
//Do some Stuff
}
//if file contents is not valid, display form and populate values with unfiltered values
$form->populate($this->getRequest()->getPost());
}
//if form is not valid, it should stay populated and display element errors
}
//if not post send form to view
$this->view->form = $form;
}
This example should provide the basic controller workflow for this type of problem. I hope it addresses your question.

When form validation fails, how to pass error information for new try?

I'm developing a form validation class in PHP. When form validation fails, I can easily redirect again to the form's html page but without error information. I would like to redirect to the form's page with the specific errors about which fields failed and why.
How should I do this? Should I send information back via GET or POST? and in which format? Would really to see some code to see how people tackled this problem.
Thanks!
You could use the header() function. So just check the fields that are posted:
if(!$form->valid()){
$msg = "Form is not valid";
} else {
//Don't know if you want this
$msg = "Form is valid";
}
header("Location: [page where you came from]?msg=" . urlencode($msg));
Then in the page where you're redirecting to use
if(isset($_GET['msg]))
echo urldecode($_GET['msg']);
to echo the message. If you are using other get variables in the location of the header function, of course, use &msg=" . urlencode($msg). (You may also want to return the values that the user submitted, so the user doesn't have to fill out the entire form again if he makes 1 mistake.
I agree with user187291's suggestion of using $_SESSION because:
It doesn't hijack the URI like using $_GET (you would never want a static link to a status message). Users could press "back" to the page with your form and still see a status message because the URI says so.
Print and unset it in the same run, you won't be able to use it more than once (which is what you want?!)
If you're going with AJAX, $_GET is more widely used for retreiving values, which you are doing from the validation controller.
there are number of approaches
pass errors in GET when redirecting back like you said
use sessions to store error info, on the form page check Session for errors
do not redirect after failure, just output form again along with error messages
ajax submits
which one to use depends on the application. For most apps sessions method is most appropriate.
Something like this:
// Pseudo Code
function isValid($parm) {
$return = false;
if(preg_match(/^[a-zA-Z]+$/, $parm) {
$return = true;
}
return $return;
}
$firstname = $_GET["fname"];
$lastname = $_GET["lname"];
$validFirstName = isValid($firstname);
$validLastName = isValid($lastname);
if($validFirstName == true && $validLastName == true) {
echo "It's all good";
// Do what you need to like, Submit
} else {
echo "Please retry";
// Display error message
}
I use a class to interface with $_POST, similar to the following:
// create the object
$post = new PostData();
// register your requirements... write whatever methods you need
// for each call,read $_POST, check criteria, and mark the field
// as good or bad...
$post->required ('LastName');
$post->required ('FirstName');
$post->numeric ('Age');
$post->optional ('MiddleInitial');
$post->regExp ('/\d{3}/','AreaCode');
$post->email ('Email');
// check the status
if (!$post->isValid ())
{
$_SESSION['FailedPostData'] = $post;
header ('Location: page.php');
}
// normal form processing
Then, on page.php, you can see if FailedPostData is in the session, read it to find the info entered last time, as well as which fields that failed. I use a template engine with macros that let me easily re-populate the form inputs and mark the failures. Otherwise you might end up with lots of code for a simple form...
You'll also need a mechanism to be sure that stale FailedPostData doesn't hang around in the session and confuse things.
I am doing it this way. Beginner in php so not sure if this is the best way to do:
HTML Form Page:
<form id="abc" method="post" action="validate.php">
PHP Page
..validation conditions..call a function if things do not match
function display_error($error) {
echo "<html><body><link href='style.css' rel='stylesheet' type='text/css'><br><center><h2>";
echo "$error";
echo "</h2></center><br><br>";
echo "<center><input type='button' value='Go Back' onClick='history.go(-1)' style='width:100px; height:28px; font-size:16px'></center>";
echo "</body></html>";
}
Clicking on the back button takes you back to the html page with the data intact.

Categories