Jump to content

Form Validation Design


HenryCan

Recommended Posts

I've been messing around with form validation and have got my code working quite well. I've replaced all the mysql() calls with PDO code and it is all working. I'm validating the form input on the client side via JQuery's validate plugin and validating it again on the server side with PHP code. I've tested the server validation with Javascript disabled in my browser and it works fine.

 

But I have a bad feeling that I'm not doing things in the best way. I'm still new at PHP and I suspect that my basic design is just not what it should be. I hope people here can suggest a better approach.

 

I've basically got three files associated with each form:

  • an .shtml page that contains the form itself and invokes JQuery to validate the contents of the form on the client side
  • a php file that re-validates the input data from the form and then inserts a row to a mysql database via PDO
  • a "thank you" .shtml page that confirms that the data has been successfully stored in the database

The PHP file includes both of the .shtml pages and the main .shtml page, the one with the form, identifies the .PHP file in the Action parameter.

 

Here's why I think the design is not right:

  • Error messages from server validation appear at the bottom of the same page containing the form. That's actually what I want but I'm concerned that when I look at the page source in the browser, it shows the errors are written after the </html> tag. That doesn't feel right to me. By the same token, if there are no errors, I write a couple of lines of text to the page that tell the user that there were no (server-side) validation errors and that the data was successfully written to the database. Those lines also appear at the bottom of that same page after the </html> tag.
  • Assuming there were no server-side validation errors, the contents of the "thank you" page appear directly below everything else on the page. Again, that is after the </html> page.

Am I correct in believing that my design is not ideal?

 

I'd be willing to post my code here if it would help you get a better picture of what I'm doing. In fact, I asked a week or two back if I could post it and get people to walk through it but no one replied one way or the other to indicate if that was acceptable in this forum so I took that as a "no".

Link to comment
Share on other sites

If you post the code, we'll be much better equipped to give you some proper feedback. Make sure to post only the relevant code though, as very few people are interested in wading through hundreds of lines of code largely unrelated to the question at hand.

Edited by Christian F.
Link to comment
Share on other sites

Here is the code then.

 

First, the main .shtml page. As per Christian's request, I'm omitting the vast majority of the JQuery code. It seems to work just fine and it is positioned the same as in the various examples I found online. This file is topic_proposal_theme.shtml:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Meeting Topic Proposal - Theme</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.10.0/jquery.validate.js"></script>
<script>
$(document).ready(function(){
$("#topic_proposal_theme").validate({
// jQuery code - omitted
});
});
</script>
<style type="text/css">
label.error { float: none; color: red; background-color: yellow; padding-left: .5em; vertical-align: top; font-weight:bold}
</style>
<link rel="stylesheet" type="text/css" href="css/main.css" media="screen"/>
<link rel="stylesheet" type="text/css" href="css/print.css" media="print"/>
</head>
<body>
<h1>Meeting Topic Proposal - Theme</h1>
<form id="topic_proposal_theme" method="post" action="topic_proposal_theme.php">
<p>Use this form to make a suggestion for a future meeting topic. Complete the form and press the Submit button. To clear the form without submitting it, press the Reset button.</p>
<div id="errorbox"><ul></ul></div>
<p>Topic proposal submitted by (e.g. Doug B.): <input type="text" name="proposer" id="cproposer" size="30" maxlength="30"/></p>
<fieldset><legend>Proposed Topic</legend>
<p>Title (e.g. The future of Genetic Engineering): <input type="text" name="title" id="ctitle"  size="50" maxlength="50"/></p>
</fieldset>
<p></p>
<p>What will we discuss? (e.g. How human beings will change physically and emotionally if genetic engineering proceeds.)</p>
<p><textarea name="discuss" id="cdiscuss" rows="10" cols="50"></textarea></p>
<p>What, if anything, do we have to do to prepare for the meeting? (e.g. Read a Wikipedia article on genetic engineering and any novel in which genetic engineering is a key plot element.)</p>
<p><textarea name="prepare" id="cprepare" rows="10" cols="50"></textarea></p>
<p><input type="checkbox" name="related" id="crelated" value="Related">There is a related topic that should be presented at the same meeting.</p>
<p>Additional Comments (e.g. It would be helpful if you could prepare a list of genetic enhancements that you would like to have.):</p>
<p><textarea name="comments" id="ccomments" rows="10" cols="50"></textarea></p>
<p>
<input type="hidden" name="_submit_check" value="1"/>
<input name="submitForm" id="submitForm" type="submit" value="Submit"/>
<input name="reset" id="reset" type="reset" value="Reset"/>
</p>
</form>
<p><!--valid XHTML 1.0 Strict code--><a href="http://validator.w3.org/check/referer">
<img class="noprint unbordered"  src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Strict!" height="31" width="88"/></a></p>
</body>
</html>

 

This is the PHP code, topic_proposal_theme.php. This one is complete. I'm not enclosing the SQL that creates the table. The insert works just fine and I have no concerns about it.

 

<?php
   $debug = 0;
   $Defaults = array();
   $Errors = array();
   include('topic_proposal_theme.shtml');
   if ($debug) {
    echo 'Current php version: ' . phpversion() . '<br/>'; //Gives 5.3.19 on absolut server on 2013-01-18
    echo 'Request method: ' . $_SERVER['REQUEST_METHOD'] . '<br/>'; //determine request method
   }

   if ($debug) {echo "Count: " . count($_POST) . "<br/>";}

   /* If any of the form elements were completed, validate them. If all elements were valid, insert a record
 * to the database. */
   if (count($_POST) > 0) {
	    $Defaults = $_POST;

	    $proposer = $_POST['proposer'];
	    $title = $_POST['title'];
	    $discuss = $_POST['discuss'];
	    $prepare = $_POST['prepare'];
	    $related = $_POST['related'];
	    $comments = $_POST['comments'];

	    if ($debug) {
		    echo "Proposer: $proposer<br/>";
		    echo "Title: $title<br/>";
		    echo "Discuss: $discuss<br/>";
		    echo "Prepare: $prepare<br/>";
		    echo "Related: $related<br/>";
		    echo "Comments: $comments<br/>";
	    }

	    /* Verify that all mandatory fields contain data. */
	    if (empty($proposer) || strlen(trim($proposer))==0) {
			    $Errors[] = 'The name of the person proposing the topic is a required field. Example: Bob T.';
	    }

	    if (empty($title) || strlen(trim($title))==0) {
			    $Errors[] = 'The title is a required field. Example: The future of genetic engineering';
	    }

	    if (empty($discuss) || strlen(trim($discuss))==0) {
		    $Errors[] = 'The discussion is a required field. Example: Consider how human beings will change physically and emotionally if trends continue.';
	    }

	    if (empty($prepare) || strlen(trim($prepare))==0) {
		    $Errors[] = 'The preparation is a required field. Example: Read a Wikipedia article and Holy Fire by Bruce Sterling.';
	    }
	    //Ensure that the description of what is to be discussed does not exceed the maximum.
	    $max_discuss_length = 500;
	    if (strlen(trim($discuss))>500) {
		    $Errors[] = 'The discussion cannot exceed $max_discuss_length characters. Please shorten your input.';
	    }
	    //Ensure that the description of the preparation does not exceed the maximum.
	    $max_prepare_length = 500;
	    if (strlen(trim($prepare))>500) {
		    $Errors[] = 'The preparation cannot exceed $max_prepare_length characters. Please shorten your input.';
	    }

	    /* Cross checks */
	    //None   

	    if (count($Errors)==0){
		    echo "<h3>Your data has all been validated successfully. Attempting to insert into database...</h3>";
		    //If the related checkbox is unchecked, pass a value of No to the database. Otherwise, pass Yes to the database.
		    $related = ($related=="") ? "No" : "Yes";
		    Insert_Proposal($proposer, $title, $discuss, $prepare, $related, $comments);				   
		    }
	    else {
		    echo "<h4>The form contains errors as noted below. Please fix them and then press the Submit button again.</h4>";
		    foreach ($Errors as $oneError) {
			    echo "<p class='red'>" . $oneError . "</p>";
		    }
	    }
   }

   function Insert_Proposal($proposer, $title, $discuss, $prepare, $related, $comments) {
    $debug = 0; //temporary

    include('#pdo-signin-insert.shtml'); //Sign in, connect and select database

    $date_proposed = date('Y-m-d'); //The date is generated here, not obtained from the form.

    if ($debug) {
	    echo "Date proposed: $date_proposed<br/>";
	    echo "Proposer: $proposer<br/>";
	    echo "Title: $title<br/>";
	    echo "Discuss: $discuss<br/>";
	    echo "Prepare: $prepare<br/>";
	    echo "Related: $related<br/>";
	    echo "Comments: $comments<br/>";
    }

    try {
	    $stmt = $db->prepare("INSERT INTO TopicProposals_Themes(Date_Proposed, Proposer, Title, Discuss, Prepare, Related, Comments) VALUES (:date_proposed, :proposer, :title, :discuss, :prepare, :related, :comments)");
	    $stmt->execute(array(':date_proposed' => $date_proposed, ':proposer' => $proposer, ':title' => $title, ':discuss' => $discuss, ':prepare' => $prepare, ':related' => $related, ':comments' => $comments));
	    $affected_rows = $stmt->rowCount();
	    }
    catch (PDOException $excp) {
	    echo "Error during insert into TopicProposals_Themes. Message: " . $excp->getMessage();
	    exit(1);
    }

    include('topic_proposal_accepted.shtml');					   
   }
?>

 

And this is the "thank you" .shtml file. I doubt there's anything controversial in it, although I can't help but wonder if I need some code that "clears the screen" (deletes the HTML that was previously being displayed) before the Thank You page appears.

 

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" > 
<head>
<title>Thank You!</title>
</head>
<body>
<h1>Thank you!</h1>
<p>Your proposed topic has been added to the database. It will be considered at the next planning session. Planning sessions are typically held during the regular June and December meetings.</p>
<p>You can <a href="choosing_topics.shtml">make another suggestion</a> or <a href="index.shtml">return to the home page</a>.</p>
<p><!--valid XHTML 1.0 Strict code--><a href="http://validator.w3.org/check/referer">
<img class="noprint unbordered"  src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Strict!" height="31" width="88"/></a></p>
</body>
</html>

Link to comment
Share on other sites

Have you a link to a working live website?

 

And my guess would be that you are including a file into another file that has already defined the <html>, <head> and so forth tags. Have you tried setting the thank you file to just:

 

<h1>Thank you!</h1>
<p>Your proposed topic has been added to the database. It will be considered at the next planning session. Planning sessions are typically held during the regular June and December meetings.</p>
<p>You can <a href="choosing_topics.shtml">make another suggestion</a> or <a href="index.shtml">return to the home page</a>.</p>

 

You can change the title by, in the main file, setting it to:

 

<title><?php echo $title;?></title>

 

and then setting the value of $title accordingly.

Edited by Jonline
Link to comment
Share on other sites

Yes, you can see/try the form yourself by going to http://sfl.x10host.com/topic_proposal_theme.php.

 

I can certainly try the change you're proposing but isn't it still going to get written AFTER the </html> tag? If so, is it really worth doing?

 

And yes, I think you'll see in my code that all the echos that I'm doing in topic_proposal_theme.php will get written after the original form page (topic_proposal_them.shtml), which includes an </html>, has already been written. The "thank you" page gets written after that so it is inevitably too late to be written before the </html> tag.

 

Is my solution as simple as not including the </body> and </html> tags in topic_proposal_theme.shtml and simply putting it on the "thank you" page?

 

I'm not sure if the three individual pages should all pass HTML validation as separate files? Or is it okay if they are viewing more as fragments that won't pass an HTML validation separately?

Link to comment
Share on other sites

Well as you are restating the <html> tags, you will be defining what is effectively a new page. Think of it like a class, you may have many in one namespace, but each is seperate. Given that you are executing the code before the final </html> tag, this is the only logical reason. I wouldn't get too worked up over the W3C validation checks, type in Google or Facebook and you'll see 100s of errors. Out of interest, as you are including the file then I would suggest it need not.

Edited by Jonline
Link to comment
Share on other sites

Sorry, Jonline, your last remark is not completely clear. Am I correct in understanding that if I simply wait with writing the </body> and </html> tags until I have nothing more to write, everything will be fine? Or are you saying it's already fine the way it is now?

Link to comment
Share on other sites

topic_proposal_theme.shtml is fine

topic_proposal_theme.php is fine

 

The thank-you file, try (like I said before, it's the only logical problem area, though it may not be the problem) removing the <html>, <head> and <body> tags, so that it is purely the following:

 

<h1>Thank you!</h1>
<p>Your proposed topic has been added to the database. It will be considered at the next planning session. Planning sessions are typically held during the regular June and December meetings.</p>
<p>You can <a href="choosing_topics.shtml">make another suggestion</a> or <a href="index.shtml">return to the home page</a>.</p>

 

If you want to set the page title, then you may do the following in topic_proposal_theme.shtml:

 

<?php $title = "Meeting Topic Proposal - Theme";?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title><?php echo $title;?></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
...

 

and within the thank you page:

 

<?php $title = "Thank You!";?>
<h1>Thank you!</h1>
<p>Your proposed topic has been added to the database. It will be considered at the next planning session. Planning sessions are typically held during the regular June and December meetings.</p>
<p>You can <a href="choosing_topics.shtml">make another suggestion</a> or <a href="index.shtml">return to the home page</a>.</p>

 

As you are including the file, it will set the value of $title to be "Thank You!" and thus update your page title accordingly.

Edited by Jonline
Link to comment
Share on other sites

I can't edit anymore, but basically:

 

OK scrap what I said, I had a proper look at your code. What you are doing is submitting the form, and sending it to topic_proposal_theme.php. At the top of this PHP page, you are including topic_proposal_theme.shtml, which means anything you echo out after this included file will be done so after the contents of the file. In other words, your current set-up will always echo out after the closing HTML tag.

 

What you could do is this:

 

topic_proposal_theme.shtml:

 

<?php
 include_once('topic_proposal_theme.php');
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Meeting Topic Proposal - Theme</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.10.0/jquery.validate.js"></script>
<script>
$(document).ready(function(){
$("#topic_proposal_theme").validate({
// jQuery code - omitted
});
});
</script>
<style type="text/css">
label.error { float: none; color: red; background-color: yellow; padding-left: .5em; vertical-align: top; font-weight:bold}
</style>
<link rel="stylesheet" type="text/css" href="css/main.css" media="screen"/>
<link rel="stylesheet" type="text/css" href="css/print.css" media="print"/>
</head>
<body>
<h1>Meeting Topic Proposal - Theme</h1>



<?php
if (isset($_POST['submitForm'])) {
validateForm(pass through relevant arguments);
}
?>



<form id="topic_proposal_theme" method="post" action="topic_proposal_theme.shtml"> // note change of action[/font][/size]



[size=3][font=verdana,geneva,sans-serif]<p>Use this form to make a suggestion for a future meeting topic. Complete the form and press the Submit button. To clear the form without submitting it, press the Reset button.</p>
<div id="errorbox"><ul></ul></div>
<p>Topic proposal submitted by (e.g. Doug B.): <input type="text" name="proposer" id="cproposer" size="30" maxlength="30"/></p>
<fieldset><legend>Proposed Topic</legend>
<p>Title (e.g. The future of Genetic Engineering): <input type="text" name="title" id="ctitle" size="50" maxlength="50"/></p>
</fieldset>
<p></p>
<p>What will we discuss? (e.g. How human beings will change physically and emotionally if genetic engineering proceeds.)</p>
<p><textarea name="discuss" id="cdiscuss" rows="10" cols="50"></textarea></p>
<p>What, if anything, do we have to do to prepare for the meeting? (e.g. Read a Wikipedia article on genetic engineering and any novel in which genetic engineering is a key plot element.)</p>
<p><textarea name="prepare" id="cprepare" rows="10" cols="50"></textarea></p>
<p><input type="checkbox" name="related" id="crelated" value="Related">There is a related topic that should be presented at the same meeting.</p>
<p>Additional Comments (e.g. It would be helpful if you could prepare a list of genetic enhancements that you would like to have.):</p>
<p><textarea name="comments" id="ccomments" rows="10" cols="50"></textarea></p>
<p>
<input type="hidden" name="_submit_check" value="1"/>
<input name="submitForm" id="submitForm" type="submit" value="Submit"/>
<input name="reset" id="reset" type="reset" value="Reset"/>
</p>
</form>
<p><!--valid XHTML 1.0 Strict code--><a href="http://validator.w3.org/check/referer">

 

topic_proposal_theme.php

 


<?php
$debug = 0;
$Defaults = array();
$Errors = array();


//////////////////////////////////////////////// include('topic_proposal_theme.shtml'); -------------- get rid of this line --------------------


if ($debug) {
echo 'Current php version: ' . phpversion() . '<br/>'; //Gives 5.3.19 on absolut server on 2013-01-18
echo 'Request method: ' . $_SERVER['REQUEST_METHOD'] . '<br/>'; //determine request method
}

if ($debug) {echo "Count: " . count($_POST) . "<br/>";}




/* If any of the form elements were completed, validate them. If all elements were valid, insert a record
* to the database. */[/font][/size]



function validateForm(pass through relevant arguments) {



if (count($_POST) > 0) {
$Defaults = $_POST;

$proposer = $_POST['proposer'];
$title = $_POST['title'];
$discuss = $_POST['discuss'];
$prepare = $_POST['prepare'];
$related = $_POST['related'];
$comments = $_POST['comments'];

if ($debug) {
echo "Proposer: $proposer<br/>";
echo "Title: $title<br/>";
echo "Discuss: $discuss<br/>";
echo "Prepare: $prepare<br/>";
echo "Related: $related<br/>";
echo "Comments: $comments<br/>";
}

/* Verify that all mandatory fields contain data. */
if (empty($proposer) || strlen(trim($proposer))==0) {
$Errors[] = 'The name of the person proposing the topic is a required field. Example: Bob T.';
}

if (empty($title) || strlen(trim($title))==0) {
$Errors[] = 'The title is a required field. Example: The future of genetic engineering';
}

if (empty($discuss) || strlen(trim($discuss))==0) {
$Errors[] = 'The discussion is a required field. Example: Consider how human beings will change physically and emotionally if trends continue.';
}

if (empty($prepare) || strlen(trim($prepare))==0) {
$Errors[] = 'The preparation is a required field. Example: Read a Wikipedia article and Holy Fire by Bruce Sterling.';
}
//Ensure that the description of what is to be discussed does not exceed the maximum.
$max_discuss_length = 500;
if (strlen(trim($discuss))>500) {
$Errors[] = 'The discussion cannot exceed $max_discuss_length characters. Please shorten your input.';
}
//Ensure that the description of the preparation does not exceed the maximum.
$max_prepare_length = 500;
if (strlen(trim($prepare))>500) {
$Errors[] = 'The preparation cannot exceed $max_prepare_length characters. Please shorten your input.';
}

/* Cross checks */
//None

if (count($Errors)==0){
echo "<h3>Your data has all been validated successfully. Attempting to insert into database...</h3>";
//If the related checkbox is unchecked, pass a value of No to the database. Otherwise, pass Yes to the database.
$related = ($related=="") ? "No" : "Yes";
Insert_Proposal($proposer, $title, $discuss, $prepare, $related, $comments);
}
else {
echo "<h4>The form contains errors as noted below. Please fix them and then press the Submit button again.</h4>";
foreach ($Errors as $oneError) {
echo "<p class='red'>" . $oneError . "</p>";
}
}
}
}

function Insert_Proposal($proposer, $title, $discuss, $prepare, $related, $comments) {
$debug = 0; //temporary

include('#pdo-signin-insert.shtml'); //Sign in, connect and select database

$date_proposed = date('Y-m-d'); //The date is generated here, not obtained from the form.

if ($debug) {
echo "Date proposed: $date_proposed<br/>";
echo "Proposer: $proposer<br/>";
echo "Title: $title<br/>";
echo "Discuss: $discuss<br/>";
echo "Prepare: $prepare<br/>";
echo "Related: $related<br/>";
echo "Comments: $comments<br/>";
}

try {
$stmt = $db->prepare("INSERT INTO TopicProposals_Themes(Date_Proposed, Proposer, Title, Discuss, Prepare, Related, Comments) VALUES (:date_proposed, :proposer, :title, :discuss, :prepare, :related, :comments)");
$stmt->execute(array(':date_proposed' => $date_proposed, ':proposer' => $proposer, ':title' => $title, ':discuss' => $discuss, ':prepare' => $prepare, ':related' => $related, ':comments' => $comments));
$affected_rows = $stmt->rowCount();
}
catch (PDOException $excp) {
echo "Error during insert into TopicProposals_Themes. Message: " . $excp->getMessage();
exit(1);
}

include('topic_proposal_accepted.shtml');
}
?>

 

thank-you page (though instead of making this a page it is probably easier to just echo this at the end of your PHP script):

 

<h1>Thank you!</h1>
<p>Your proposed topic has been added to the database. It will be considered at the next planning session. Planning sessions are typically held during the regular June and December meetings.</p>
<p>You can <a href="choosing_topics.shtml">make another suggestion</a> or <a href="index.shtml">return to the home page</a>.</p>

 

 

 

If you want to set the page title based upon the page, then you may do the following in topic_proposal_theme.shtml:

 

// Very top of document
<?php
 include_once('topic_proposal_theme.php');
 $title = "Meeting Topic Proposal - Theme";
?>
<!DOCTYPE html>
<html>
...

 

and within the thank you page:

 

<?php $title = "Thank You!";?>
<h1>Thank you!</h1>
<p>Your proposed topic has been added to the database. It will be considered at the next planning session. Planning sessions are typically held during the regular June and December meetings.</p>
<p>You can <a href="choosing_topics.shtml">make another suggestion</a> or <a href="index.shtml">return to the home page</a>.</p>

 

As you are including the file, it will set the value of $title to be "Thank You!" and thus update your page title accordingly.

 

--

 

I've given up trying to remove any and codes, they keep reappearing when trying to delete them!

Edited by Jonline
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.