Tuesday, August 11, 2009

Ten PHP Gotchas

guarantee that you will do all the things that I mention in this chapter. It’s not possible to write programs without making these mistakes. The trick
is to find out how to recognize them, roll your eyes, say, “Not again,” and then fix them. One error message that you will see many times is

Parse error: parse error in c:\test.php on line 7

This is PHP’s way of saying, “Huh?” It means it doesn’t understand some­ thing. This message helpfully points to the file and the line number where PHP got confused. Sometimes it’s directly pointing at the error, but some­ times PHP’s confusion results from an error earlier in the program.

Missing Semicolons

Every PHP statement ends with a semicolon (;). PHP doesn’t stop reading a statement until it reaches a semicolon. If you leave out the semicolon at the end of a line, PHP continues reading the statement on the following line. For instance, consider the following statement:

$test = 1 echo $test;

Of course, the statement doesn’t make sense to PHP when it reads the two lines as one statement, so it complains with an error message, such as the annoying

Parse error: parse error in c:\test.php on line 2

Before you know it, you’ll be writing your home address with semicolons at the end of each line.

Not Enough Equal Signs

When you ask whether two values are equal in a comparison statement, you need two equal signs (==). Using one equal sign is a common mistake. It’s per­ fectly reasonable because you have been using one equal sign to mean equal since the first grade when you discovered that 2 + 2 = 4. This is a difficult mis­ take to recognize because it doesn’t cause an error message. It just makes your program do odd things, like infinite loops or if blocks that never execute. I’m continually amazed at how long I can stare at

$test = 0;
while ( $test = 0 )
{
$test++;
}

and not see why it’s looping endlessly.

Misspelled Variable Names

This is another PHP gotcha that doesn’t result in an error message, just odd program behavior. If you misspell a variable name, PHP considers it a new variable and does what you ask it to do. Here’s another clever way to write an infinite loop:

$test = 0;
while ( $test == 0 )
{
$Test++;
}

Remember: To PHP, $test is not the same variable as $Test.

Missing Dollar Signs

A missing dollar sign in a variable name is really hard to see, but at least it usually results in an error message so that you know where to look for the problem. It usually results in the old familiar parse error:

Parse error: parse error in test.php on line 7

Troubling Quotes

You can have too many, too few, or the wrong kind of quotes. You have too many when you put quotes inside of quotes, such as

$test = “<table width=”100%”>”;

PHP will see the second double quote (“) — before 100 — as the ending double quote (“) and read the 1 as an instruction, which makes no sense. Voilà! Another parse error. The line must be either

$test = “<table width=’100%’>”;

or

$test = “<table width=\”100%\”>”;

You have too few quotes when you forget to end a quoted string, such as

$test = “<table width=’100%’>;

PHP will continue reading the lines as part of the quoted string until it encoun­
ters another double quote (“), which might not occur for several lines. This is one occasion when the parse error pointing to where PHP got confused is not pointing to the actual error. The actual error occurred some lines previ­ ously, when you forgot to end the string.

You have the wrong kind of quotes when you use a single quote (‘) when you meant a double quote (“) or vice versa. The difference between single and double quotes is sometimes important, and I explain it in Chapter 6.

Invisible Output

Some statements, such as the header statement, must execute before the pro­ gram produces any output. If you try to use such statements after sending output, they fail. The following statements will fail because the header mes­ sage isn’t the first output:

<html>
<?php
header(“Location: http://company.com”);
?>

<html> is not in a PHP section and is therefore sent as HTML output. The fol­
lowing statements will work:

<?php
header(“Location: http://company.com”);
?>
<html>

The following statements will fail:

<?php
header(“Location: http://company.com”);
?>
<html>

because there’s one single blank space before the opening PHP tag. The blank space is output to the browser, although the resulting Web page looks empty. Therefore, the header statement fails because there is output before it. This
is a common mistake and difficult to spot.

Numbered Arrays

PHP believes the first value in an array is numbered zero (0). Of course, humans tend to believe that lists start with the number one (1). This funda­ mentally different way of viewing lists results in us humans believing an array isn’t working correctly when it’s working just fine. For instance, consider the following statements:

$test = 1;
while ( $test <= 3 )
{
$array[] = $test;
$test++;
}
echo $array[3];

Nothing is displayed by these statements. I leap to the conclusion that there’s something wrong with my loop. Actually, it’s fine. It just results in the follow­ ing array:

$array[0]=1
$array[1]=2
$array[2]=3

And doesn’t set anything into $array[3].

Including PHP Statements

When a file is read in using an include statement in a PHP section, it seems reasonable to me that the statements in the file will be treated as PHP state­ ments. After all, PHP adds the statements to the program at the point where I include them. However, PHP doesn’t see it my way. If a file named file1.inc contains the following statements:

if ( $test == 1 )
echo “Hi”;

and I read it in with the following statements in my main program:

<?php
$test = 1;
include (“file1.inc”);
?>

I expect the word Hi to appear on the Web page. However, the Web page actu­
ally displays this:

if ( $test == 1 ) echo “Hi”;

Clearly, the file that is included is seen as HTML. To send Hi to the Web page,
file1.inc needs to contain the following statements:

<?php
if ( $test == 1 )
echo “Hi”;
?>

Missing Mates

Parentheses and curly brackets come in pairs and must be used that way. Opening with a ( that has no closing ) or a { without a } will result in an error message. One of my favorites is using one closing parenthesis where two are needed, as in the following statement:

if ( isset($test)

This statement needs a closing parenthesis at the end. It’s much more diffi­ cult to spot that one of your blocks didn’t get closed when you have blocks inside of blocks inside of blocks. For instance, consider the following.

376 Part V: The Part of Tens

while ( $test < 3 )
{
if ( $test2 != “yes” )
{
if ( $test3 > 4 )
{
echo “go”;
}
}

You can see there are three opening curly brackets and only two closing ones. Imagine that 100 lines of code are inside these blocks. It can be difficult to spot the problem — especially if you think the last closing bracket is closing the while loop, but PHP sees it as closing the if loop for $test2. Somewhere later in your program, PHP might be using a closing bracket to close the while loop that you aren’t even looking at. It can be difficult to trace the problem in a large program.

Indenting blocks makes it easier to see where closing brackets belong. Also, I
often use comments to keep track of where I am, such as

while ( $test < 3 )
{
if ( $test2 != “yes” )
{
if ( $test3 > 4 )
{
echo “go”;
} // closing if block for $test3
} // closing if block for $test2
} // closing while block

Confusing Parentheses and Brackets

I’m not sure whether this is a problem for everyone or just a problem for me because I refuse to admit that I can’t see as well as I used to. Although PHP has no trouble distinguishing between parentheses and curly brackets, my eyes are not so reliable. Especially while staring at a computer screen at the end of a ten-hour programming marathon, I can easily confuse ( and {. Using the wrong one gets you a parse error message.

0 comments: