Spelling mistakes give you a few gray hairs - Page 3
October 2, 2000
Unlike other languages which require variables to explicitly be declared,
PHP allows you to automatically use the variables without any explicit
declaration. A spelling mistake in a variable name is one of the most
frustrating PHP errors.
<? function Combine ($FirstHalf, $SecondHalf){ //Declare a function which
//accepts two variables
$Combined_String=$FirstHalf.$SecondHalf;
//Use . concatenation operator to
//combine variables FirstHalf and
//SecondHalf into one string
return $Combined_String; //Return the value
}
$FirstString="WDVL - ";
$SecondString="Illustrated Encyclopedia";
$Combine_Result=Combine ($FirstString, $SecondString);
print $Combined_Result;
?>
When you run this example you will see a browser error resulting from no
data being returned by the script. This is an extreme case used to
enforce my point. You will most likely encounter this error in a more
subtle form. As you've probably already guessed we made a spelling mistake
which resulted in a new NULL string variable being created.
Our statement
print $Combined_Result;
should have read
print $Combine_Result;
without the 'd' in Combined_Result. Realistically a spelling error
anywhere in this script may cause this error. If you suspect this error
a good approach is to print some text before and after the variable.
print "The Combined Result is: |".$Combined_Result."|";
The result of replacing the print statement with this line is
The Combined Result is: ||
with no space in between the two "pipes" ('|'). You may then
use this approach, printing the variable contents, to move backward in your
program execution and print variable values until you locate the offending
line. Since this is a very common and frustrating error I will look at a
more subtle example which is a regular occurrence on the PHP mailing list.
Lets assume you have to display a web page if the user enters the correct
username and password,
<?
$Password="Secret"; //Define the required Password
$Name="admin"; //Define the required UserName
//This function will verify whether the arguments $UserPassword
//and $UserName are equal to the global variables and will
//return 1 for true and 0 for false.
function VerifyPassword ($UserPassword, $UserName){
if ($Password=$UserPassword && $Name=$UserName){
return 1;
}
else { return 0;
}
}
//The if statement is true whenever the condition, in this case
//VerifyPassword() returns a value other than 0.
if (VerifyPassword ("foo1ish", "admin")){
print "The Password is correct";
}
else {
print "I'm sorry, the password is incorrect";
}
?>
We called our VerifyPassword function with an incorrect password, but when
we run this program we see
The Password is correct
We could have an error anywhere in our code. Let's use the process of
elimination to track it down. First we are not sure whether our final
"if" statement is correct. It looks correct, but so does
everything else, and we have to start somewhere. So we will print out the
result of our VerifyPassword() function. We comment out our if
statement and replace it with an equivalent print statement.
<?
$Password="Secret"; //Define the required Password
$Name="admin"; //Define the required UserName
//This function will verify whether the arguments $UserPassword
//and $UserName are equal to the global variables and will
//return 1 for true and 0 for false.
function VerifyPassword ($UserPassword, $UserName){
if ($Password=$UserPassword && $Name=$UserName){
return 1;
}
else { return 0;
}
}
//The if statement is true whenever the condition, in this case
//VerifyPassword() returns a value other than 0.
print "The result of VerifyPassword() is: ";
print "VerifyPassword ("foo1ish", "admin");
//Commented out the old statement
/*if (VerifyPassword ("foo1ish", "admin")){
print "The Password is correct";
}
else {
print "I'm sorry, the password is incorrect";
}
*/
?>
Since we supplied the wrong password the result of calling verify password
should be 0 (false). We run the statement and see
The result of VerifyPassword() is: 1
Now we know know that the problem is somewhere in our
VerifyPassword() function. Looking at the code for that function we
can suspect that there is most likely an error with our "if"
statement. So we remove our original comments, our debugging print
statements and comment out the "if" statement inside the
VerifyPassword() function. A good practice is to take advantage of
the fact that any equality test such as
1==1
will evaluate to either true or false. We will cast this result to an
integer
(int) (1==1);
and we should see 0 for false and not 0 (most likely 1) for true. Here are
our debugging print statements.
print "UserPassword => $UserPassword, Password => $Password, ";
print "Password==UserPassword => ".(int)($Password==$UserPassword)."<BR>";
print "UserName => $UserName, Name => $Name, ";
print "Name==UserName => ".(int)($Name==$UserName)."<BR>";
The statements will result in output of the form Name=Value and include
the result of the equality test between the two variables. Here is our
output.
UserPassword => foo1ish, Password => , Password==UserPassword => 0
UserName => admin, Name => , Name==UserName => 1
I'm sorry, the password is incorrect
Oh, oh. We can already see a problem with this statement. The values for
Password and Name seem to be null. Well no wonder our equality statements
don't work.
Why is the value of $Password null? Looking at the code we can clearly see
that $Password is properly assigned, but for some reason it's value is not
accessible inside the function. We take a look at the
PHP manual under the
Variables => Variable Scope
section
and quickly find out that in order to use variables inside a function they
have to be declared as global. Great, we add
global $Password, $Name;
as the first line of our VerifyPassword()
function and re-run our code.
UserPassword => foo1ish, Password => Secret, Password==UserPassword => 0
UserName => admin, Name => admin, Name==UserName => 1
The Password is correct
What? We should have seen a message indicating the password is incorrect.
A close look at our if statement reveals that we forgot to use the equality
test (==)(two = signs) operator. Instead we used the assignment operator
(single = sign) and ended up assigning the value of $UserPassword to
$Password. This naturally evaluates to true since anything not 0 is
considered to be true. So let's correct our final two mistakes by adding
the equality test to our "if" statement and remove our debugging
statements. Here is our complete program.
$Password="Secret"; //Define the required Password
$Name="admin"; //Define the required UserName
//This function will verify whether the arguments $UserPassword
//and $UserName are equal to the global variables and will
//return 1 for true and 0 for false.
function VerifyPassword ($UserPassword, $UserName){
//Indicate that we want to use the globally declared
//versions of these variables
global $Password, $Name;
//Corrected our equality test to include ==
if ($Password==$UserPassword && $Name==$UserName){
return 1;
}
else { return 0;
}
}
//The if statement is true whenever the condition, in this case
//VerifyPassword() returns a value other than 0.
if (VerifyPassword ("foo1ish", "admin")){
print "The Password is correct";
}
else {
print "I'm sorry, the password is incorrect";
}
When we execute it we see
I'm sorry, the password is incorrect.
O.k. We'll enter the correct password and re-run the example in order to
make sure it works in both cases. We see
The Password is correct
Beautiful. That wasn't so hard? So what happened to the second example of
more subtle spelling mistakes that I promised? Well this was it, without
the spelling mistakes. My goal was not to teach you how to avoid spelling
mistakes, they are inevitable. I wanted to give you an idea of how to
approach those hard to find errors.
Every sentence must end with a period - Page 2
Debugging PHP: Did You Remember to "Dot All Your I's and Cross All Your T's"?
MySQL and PHP: They have some "TWERPS" of their own - Page 4
|