Advanced Form Processing with PHP and Javascript
Intended Audience
Prerequisites
Introduction
What Is Javascript, and What Is Not
Utilizing Javascript to Reduce Traffic
What if Javascript has Gone Away?
Passing Data From PHP To Javascript
Using Regular Expressions
Tips & Tricks (Processing)
Tips & Tricks (Designing Form)
Sample Codes
Conclusion
Intended Audience
This article is intended for intermediate level PHP
programmers, who know how to use web forms to gather data, and how to
communicate with database systems or filesystem to store the data, but are
unaware or uninformed about the inspection process between these two steps.
Prerequisites
- Basic understanding of HTTP.
- Basic command of Javascript.
- Experience with HTML form elements.
Introduction
When building a web site, sooner or later you will need a
form. Forms are the best way of gathering data from visitors. Your forms can be
as small as a login form, or as large as a membership subscription form asking
for lots of input. Obviously, the bigger the form, the more information there is
to process, and the greater the challenge.
When inspecting form data, the two most important issues you
have to worry about are intrusion,and gathering as much useful data as possible
from your visitors. Although these issues appear to lay on just opposite sides -
you want to collect lots of data, but you have to put restrictions against
intruders – it is actually possible to do both. By taking a few precautions you
can eliminate 95% of intruders while forcing visitors to supply the data you
want.
You have tools for optimization of form’s inspection
process, both client side and server side. Client side, the most important of
themtools are scripting languages, particularly Javascript. Utilizing
Javascript, you can limit and check form data while it’s still on the
client side.
On the server side, you need nothing but PHP. But, you should
be aware that some common coding mistakes in PHP may become deadly. Have a look
at zend.com’s articles titled Coding Mistakes Part I, II, III for more
details.
What Is Javascript, and What Is Not?
Javascript is popular client side scripting language used for
controlling objects on the web page. It’s code is embedded and sent to the
client’s browser in the HTML. As long as the client does not make a new
request from the server, Javascript will stay and run on the client. In the same
way, Javascript’s effects stay on the client side until submission to the
server. That’s why it’s client-side. And you cannot access client
machine’s resources like filesystem or data sources. That’s why
it’s called scripting language, not programming. Javascript deals with
objects on the web page only.
Javascript is NOT a security tool. Since your source is sent
to the client, who can talk about security? Javascript is used simply to save
server bandwidth. “Client-side scripting” and “security”
are a contradiction in terms.
Rules are well and fine so long as people obey them.
Javascript sets rules for users without any evil intention. But, an unscrupulous
and knowledgeable intruder won’t mind breaking a few rules in an effort
to find a gate which you forgot to close.
Utilizing Javascript to Reduce Traffic
Javascript is capable of controlling HTML objects on a page,
including form objects. You can minimize network traffic between server and
client by utilizing Javascript as a pioneer.
Consider this case: You have a web page including a form with
username and password fields, and both cannot be shorter than 6 characters. You
have two alternatives: Let Javascript check this constraint first, client side,
then have PHP take over, server side; or have everything dealt with by PHP
server side. Evaluate the pseudo alternatives when user entered 5 characters in
username field:
Javascript + PHP
| PHP
|
There are two steps (1,5) causing traffic between server and client when Javascript is utilized before
PHP, while there are four (1,3,5,7) with PHP only. (See sample code 4 for this example’s source.)
Does server workload matter when utilizing Javascript? As for
PHP’s CGI nature, every time your script called, an instance of
php’s executable is created, using up memory and processor resources. As
the execution finishes, the file dies and resources get freed. Executing a few
PHP script won’t usually overload the server unless there are huge numbers
of php instances running at the same time. The time taken to execute PHP scripts
is measured in miliseconds, and you can observe resource consumption using Task
Manager (on Windows platforms), or the command
ps –ef | grep php (on Unix platforms).
You should take server performance into account,
- When you’re expecting hundreds of visitors online at the same time
- When you have very limited server resources (for hardware, hosting etc. reasons)
If you choose average web server software and hardware,
performance is not an issue. Therefore, Javascript makes no difference to your
server’s workload. The biggest factor affecting on your site’s
performance is still bandwidth.
What if Javascript has Gone Away?
Although it’s can’t be claimed that Javascript is
available on every browser, certainly every modern browser supports it. However,
even with modern browsers, scripting can be manually disabled for security
reasons. What happens if Javascript is not enabled, or is circumvented in any
way, or if someone sent data by hand instead of filling out your form?
When coping with form processing, you have to ensure that,
- the form is displayed on the client browser and filled out,
- Javascript has gone over the form, and checked that no error occured.
If the client browser does not support Javascript, the form
will also be displayed, but JS procedures won’t be included. Against these
non-JS enabled (or purposely disabled) browsers, you can use the
<NOSCRIPT> HTML tag. This tag specifies HTML to be displayed in browsers that do not support scripting. Using
this tag, you will exclude users with very old fashioned or text-based browsers,
plus those who manually disabled scripting.
A second thing to remember: Do not use a SUBMIT type for the
button which submits the form:
<INPUT TYPE="submit" VALUE="OK" onClick="check_form(this);">
If you do, the form will be submitted regardless of your JS
procedure’s return value(s). It’s better to use a BUTTON object and
set it’s onClick event to a related JS function:
<INPUT TYPE="button" VALUE="OK" onClick="check_form(this);">
This will call the associated Javascript function to check the
form, and this function will submit it only if no error occured.
To ensure that the form is ‘really’ filled out,
rather than sent by another application or manually, you may use a noisy image
created online as a form checking technique. (See the sign-up page on hotmail.com). Zend.com has a tutorial on
Securing Forms with Noisy Images.
|
Passing Data From PHP To Javascript
Sometimes you may need to use some data back on client side.
There are 2 ways of passing data from PHP to Javascript. The first way is
directly adding PHP code in the <SCRIPT> tag, appropriate to Javascript
syntax:
<?php
$user_id = $_GET["uid"];
?>
font color="#007700"><SCRIPT LANGUAGE="Javascript1.2">
var user_id =
<?php echo($user_id);?>
;
alert("Your user ID is:" + user_id);
</SCRIPT>
A second, similar, way is to insert a HIDDEN type input field
into the page, and set it’s value with PHP. Javascript is able to access
this element’s value.
<?php
$user_id = $_GET["uid"];
?>
<SCRIPT LANGUAGE="Javascript1.2">
//You can directly access an object's value with id.
alert("Your user ID is:" + p2j.value);
</SCRIPT>
<BODY BGCOLOR=
"#FFFFFF">
<INPUT TYPE=
"hidden" ID=
"p2j" VALUE="<?php echo(
$user_id);?>
">
Using Regular Expressions
When processing form input, you often have to perform
complicated operations on strings. Regular expressions, or regexp in short, are
a powerful way of specifying complex string search and modifications. Regular
expressions are available in almost every environment. From PHP to Javascript,
or MySQL to Unix itself. Though regular expressions have different
implementations, their general logic is similar. For further information about
using regular expressions in different environments, consult related
documentation.
Normally regular expressions need more resources to run, but
they let you easily check and modify very complex strings in just a couple of
lines, which would otherwise require lots of flow control blocks (if..else,
switch etc.) to perform the same actionYeap.. That’s why it’s
logical to use them. On the other hand, excessive usage of regular expressions
overburdens your server. Thus, determining when to choose regexp is
important.
In PHP, two types of regular expression are available: Perl
compatible and POSIX 1003.2. Perl compatible regular expressions have number of
advantages over POSIX. (Refer to related documentation for further information
on regular expressions.)
In Javascript, creating regexp objects is very similar to
creating string variable definitions. If you begin and end with slashes, then
the variable will be stored as a regexp object and will be eligible for regexp
methods like compile, exec, match, test, replace. Another way is creating an
instance of theYes, it’s a specific class name in Javascript. RegExp
object.
The syntax of string testing in Javascript is like
regexp.test(string);
Where regexp represents the regular expression, and
string is the string that this test is going to made on. The test method
checks to see if a pattern exists within a string and returns Ttrue if it does,
and false otherwise. (See sample code 3.)
Tips & Tricks (Processing)
When evaluating a user’s input, length is not the only
criterium you have to check. Remember that a space is also counted as a
character. For better auditing;
- Replace multiple spaces with a single space using replace regexp . This is
even more important when you explode the input into an array, using space as
delimiter. Multiple spaces will result in keys with empty values on the
resulting array. (See sample code 1 and 2.)
- Trim string inputs before using them in comparisons. Javascript has no trim function. See function below.
(See sample code 5.)
- Check the data types of fields. PHP has very useful functions for this purpose:
is_numeric(), is_string(), is_integer() etc.
- Quotes and some other special characters (percent sign, underscore, semicolon etc.) may cause problems
on SQL commands. Since JS has no similar function, you’d better use PHP’saddslashes()
function before querying SQLs. This function adds slashes as an escape character for those special
characters, including null. Not only characters, but some keywords are reserved
and meaningful for databases systems. Like CREATE, DROP, ALTER, DELETE, GRANT,
REVOKE.
- As a global programming rule, try to handle all exceptions in code
and never let PHP show an error message. Some error messages may reveal key
information (like physical paths) to intruders. You can also display messages
like different system messages to confuse novice intruders, such as:
$db_conn = @mysql_query('localhost', 'u', 'p') or die('ADO Connection Error 0x80000922: Microsoft Jet Engine couldn\'t be started'); // What the heck ADO is doing there J?
$recs = @mysql_query($sql, $db_conn) or die ('ADO Recordset Error 0x800A0BCD: Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record.');
- Receiving data with a method that you don’t expect indicates an intrusion attempt.
Unexpected variables are not funny either. Prefer using
$_POST[‘Variable’]syntax instead of$Variableor
$_REQUEST[‘Variable’].
Specify which method are you expecting data in. Occasionally you may actually
expect more than one. If that is the case, put them in order:
// If POST data is set, use it, otherwise use GET data.
$name = isset($_POST['name']) ? trim($_POST['name']) : trim($_GET['name']);
- If a checkbox is not checked, the
isset()function will return false when
processing. Therefore, before checking the value of a checkbox, always check if it’s set.
if (isset($_POST['read_licence_aggreement'])) {
if($_POST['read_licence_aggreement']== "Y") {
echo "User has accepted licence aggreement.";
}
}
Tips & Tricks (Designing Form)
- Always include MAXLENGTH attribute in text fields to limit the size of
field. This will save your script from an unexpected error.
- If you want a
field’s value to be displayed but without allowing the user to change it,
use READONLY boolean attribute set and also set it’s TABINDEX
attribute’s value to -1. (Using HIDDEN type of input will not display this
field on form.)
<INPUT TYPE="text" NAME="price" READONLY TABINDEX="-1">
- If you place multiple checkboxes on a form with the same name, PHP will
accept only the value of the last check box (in source order). In case you need
all the values as an array, put brackets “[]” (without quotes) after
NAME attributes of each one. (See sample code 6.)
Sample Codes
- Replacing strings using regular expressions in PHP.
<?php
// This command will replace multiple spaces with a space.
$result = ereg_replace("\s+", " ", $_POST['sentence']);
echo('Old String:'.$_POST['sentence'].'\n');echo('New String:'.$result.'\n');
?>
- Replacing strings using regular expressions in Javascript.
<SCRIPT LANGUAGE="Javascript1.2">
var r, re;//String to be checked.
var s =
"23th University Summer Olympic Gamesis going to be organized by
city of Izmir in 2005.";// Regular expression. Masks at least 1 space on global scope.
re = /\s+/g;// Replace space(s) with a space.
r = s.replace(re, " ");//See the results
alert("Old string:\n"+s);alert("New string:\n"+r);
</SCRIPT>
Note: Do not forget to add “g” (global search)
after the regular expression’s closing slash, if you want to replace ALL
matches. Otherwise, thereplacefunction will only replace the first match.
- Matching strings with regular expressions in Javascript.
<SCRIPT LANGUAGE="Javascript1.2">
// First way of defining regular expressions
// See parameters after second slash?
// i: ignore case g:global search
// This regexp means exact 5 numeric characters
var re_zip1 = /[0-9]{5}/ig;// ...and second.
var re_zip2 = new RegExp("/[0-9]{5}/", "ig");// Testing. Attention please.
alert(re_zip1.test("35140")); // true. All numeric and 5 digitsalert(re_zip1.test("3510")); // false. All numeric but 4 digits.
alert(re_zip2.test("a5140")); // false. 5 digits but not all numeric.</SCRIPT>
- Common HTML and Javascript source checking the form before submission.
<HTML>
<HEAD>
<TITLE>Sample Form</TITLE></HEAD>
<SCRIPT LANGUAGE="JavaScript1.2">
// Form object
var f=document.forms(0);// Boolen to track if error found
var foundErr;
// Form element index number which the first error occured.
var focusOn;
function check_form() {
foundErr = false; focusOn = -1;// Username field must be at least 6 chars.
if (f.user.value.length<6) {
alert ("Username too short.");
foundErr = true; focusOn = 0;}
// Password field must be at least 6 chars.
if (f.pass.value.length<6) {
alert("Password too short");foundErr = true;
if (focusOn==-1) focusOn=1;
}
//Has any error occured?
if (foundErr) {//Yes. Focus on which the first occurred.
f.elements.focus(focusOn);
} else {
// No. Submit the form.
f.submit();
}
}</SCRIPT>
<BODY BGCOLOR="#FFFFFF">
<FORM ACTION="check.php" METHOD="post">
<TABLE BORDER="0" WIDTH="100%" CELLSPACING="0" CELLPADDING="0"><TR>
<TD WIDTH="30%" ALIGN="right">Username</TD>
<TD WIDTH="70%">: <INPUT TYPE="text" NAME="user"></TD></TR>
<TR>
<TD ALIGN="right">Password</TD>
<TD>: <INPUT TYPE="password" NAME="pass"></TD></TR>
<TR>
<TD> </TD>
<TD><INPUT TYPE="button" VALUE="Submit" onClick="check_form();"></TD></TR>
</TABLE>
</FORM>
</BODY>
</HTML>
- Sample trim function in Javascript.
<SCRIPT LANGUAGE="Javascript1.2">
function trimmer(pVal) {
TRs=0;for (i=0; i<pVal.length; i++) {
if (pVal.substr(i,1)==" ") {TRs++;} else {break;}}
TRe=pVal.length-1;
for (i=TRe; i>TRs-1;i--) {if (pVal.substr(i,1)==" ") {TRe--;} else {break;}
}return (pVal.substr(TRs, TRe-TRs+1));
}
</SCRIPT>
- Retrieving Multiple Checkbox Values As An Array
If brackets are missing on names;
...
<INPUT TYPE="checkbox" NAME="s" VALUE="A" CHECKED>Checkbox 1<BR><INPUT TYPE="checkbox" NAME="s" VALUE="B">Checkbox 2<BR>
<INPUT TYPE="checkbox" NAME="s" VALUE="C">Checkbox 3<BR>...
processing script
<?php
echo '<PRE>('.(gettype($_POST['s']).') ';print_r($_POST['s']);
?>
will produce:
(string) ABut if you add [] after each element’s name,
...
<INPUT TYPE="checkbox" NAME="s[]" VALUE="A" CHECKED>Checkbox 1<BR><INPUT TYPE="checkbox" NAME="s[]" VALUE="B">Checkbox 2<BR>
<INPUT TYPE="checkbox" NAME="s[]" VALUE="C">Checkbox 3<BR>...
the same PHP code will produce the output below:
(array)
Array (
[0] => A
[1] => B[2] => C
)
from which we can see that all three boxes are
checked.
Conclusion
One of the most important mistakes you could ever make is
processing form data without any inspection for errors. Errors fall into two
categories:
- Vulgar errors, that occurred as a result of inattentiveness, carelessness or oversight.
If you know that 2 by 2 is equal to 4, but wrote down
“5” on exam sheet, this is a vulgar error.
- Logical errors, occurred as a result of ignorance, absence of information or malice. If you
think 2 by 2 is equal to 5, this is a logical error.
The above division also applies to web form filling. Normal
visitors will probably cause vulgar errors, and these errors can be handled by
Javascript. You shouldn’t expect more from Javascript. This is really
prelimination, not inspection. Against logical errors, especially those caused
by a malicious data, you have to set PHP in motion.
The methods, tips and tricks we have mentioned in this article
are introductory to advanced level of form processing. As you design complex
forms, you will need and develop more methods of inspection. Don’t forget
to share them with others!


6 comments to “Advanced Form Processing with PHP and Javascript”
February 14th, 2007 at 5:55 pm
When considering the example above, regarding the use of same name for multiple elements, when using the first method (which doesn’t allow you to send multiple values to PHP):
<INPUT TYPE="checkbox" NAME="s" VALUE="A" CHECKED>Checkbox 1<BR>
<INPUT TYPE="checkbox" NAME="s" VALUE="B">Checkbox 2<BR>
<INPUT TYPE="checkbox" NAME="s" VALUE="C">Checkbox 3<BR>
looping through the checkboxes with JavaScript is no problem:
var elements=document.formName.s;
for (var i=0; i<elements.count;i++){
myElement=elements[i];
// code for each myElement;
}
However when using the second method of naming the elements (the [] manner) :
<INPUT TYPE="checkbox" NAME="s[]" VALUE="A" CHECKED>Checkbox 1<BR>
<INPUT TYPE="checkbox" NAME="s[]" VALUE="B">Checkbox 2<BR>
<INPUT TYPE="checkbox" NAME="s[]" VALUE="C">Checkbox 3<BR>
you cannot use JavaScript in the same way because simply typing
var elements=document.formName.s[];
will throw out an error.
In this case you will have to loop through all alements of the form and search for the elements named ‘s[]‘, instead.
Here is a way to do it:
var elms=document.formName.elements;
for(var i=0;i<elms.length;i++)
if(elms[i].name==’s[]‘){
myElement=elms[i];
//code for myElement
}
March 18th, 2008 at 5:12 am
Actually, the name="s[]" is just the name of the element, that is, a string.
It’s not an array either in the DOM or in Javascript and that’s why document.formname.s[] doesn’t work.
Having several controls (that aren’t radio buttons anyway) with the same name/id is a problem though.
So, to correct the article example, just make the names unique by adding a numerator. PHP will interpret say name="s[3]" as an array with the specified index, eg $myarr=$_POST["s"]; $val=$myarr[3];
For javascript then "s[3]" becomes a unique name which is then accessible using document.formname["s[3]"] or document.getElementById("s[3]") if you prefer, assuming the ID is set to that value.
There are several ways to validate, using Javascript, an arbitrary number of fields, not the least of which would be just to use a while loop and test for the existence of "s[i]", assuming a sequential order. Alternately, if validation is initiated from the element itself, say on blur, then just pass the ‘this’ object along to your validator function (eg validate(this)) and your function can access the id, value, etc, no problem.
But, for ANY control in the DOM, it’s always name="value" or id="value" and only for radio buttons is the value considered to be the name of an array holding multiple values thus forming a tuple.
What’s cool with this construct though is that you can create logical and distinct form records all in the same form.
So, if you have, say, many people displayed in a form and want to process them all after a submit, just name each textbox as name="persons[0][fullname]", name="persons[2][fullname]", etc.
In php, just grab all the records as an array with $persons = $_POST["persons"]; …and process as with any data set.
You want to know how many people were submitted?
$rows = count($_POST["persons"]);
What’s the name of person 4?
$name = $_POST["persons"][4]["fullname"];
Why PHP does this is beyond me and not well documented AFAIK. But it is cool!
November 24th, 2008 at 10:12 pm
I’m trying to build a PHP/MySQL registration form for our local Little League organization. I wanted to have one form that parents could use to register up to 5 children.
I’ve asked around and the usual response is to have two tables, one for the parents and another for the players but I think this would require submitting two forms at worst or a multipage form at best. This isn’t really what I’m looking for, I need to keep the registration as simple as possible. The parents will not log back in later so I’m not creating user accounts or anything fancy. Just one simple form that parents can use to register their kids.
Here is a quick example of the information I’d like to collect:
Parents:
Name
Address
Home Phone
Work Phone
Email1
Email2
Then I need to collect the following information repeating up to 5 times:
First Name
Last Name
DOB
Years Played
School
League (pulldown menu)
For each child entered into the form I’d like to have one row inserted into the MySQL database with the play’s information and their parent’s information. There will be a lot of duplicate information but the form will be simple enough not to scare off the parents and the league is small enough that even with the duplicate information, the database should run just fine.
April 26th, 2009 at 6:56 pm
Great Post! It saved me a lot of time and mystery. Easy to read and follow. Thanks!
I did notice one syntax error…in the below section:
Passing Data From PHP To Javascript
var user_id = <?php echo($user_id);?> ;
SHOULD BE:
var user_id = "<?php echo($user_id);?>" ;
otherwise string is undefined.
Thanks again!
Chad
http://blog.jellogroup.com
September 2nd, 2009 at 12:35 am
This worked for me.
I didnt wanna do a page refresh.
I wanted to pass the value of a JS variable to a php function on the same page without having a page refresh or calling a 2nd php script
<script type=’text/javascript’>
<?php $abc ?> = document.write(document.getElementById(‘report_nam e’).value ); <?php ;?>;
</script>
<?php $obj1->getItem( $abc); ?>
$abc is the variable in which i get the JS variable value.
JS variable value is read using "document.getElementById"
I then pass the value of $abc in a php function as:-
<?php $obj1->getItem( $abc); ?>
July 30th, 2011 at 6:34 am
I have hart time to get this done. My code is as follow. And it’s not working. Will you please tell me why?
if($_SESSION['lid'] == 11)
{
$lang = 11;
//If it ran ok.
echo $lang;
?>
<script language="javascript1.2">
var jslid = "<?php echo($lang); ?>";
alert("your language is:" + lang);
<!–if (jslid == 11) –>
document.write(jslid);
pph = new PramukhPhoneticHandler();