12.2 Common Programming Errors

Now that we've discussed what errors PHP can produce, let's discuss how to fix them. In this section, we focus on situations where error messages aren't produced or are less useful in helping to find the bug. In particular, we focus on the common mistakes that even experienced programmers make.

12.2.1 A Page That Produces Partial or No Output

One of the most common problems in debugging PHP scripts is seeing:

  • Nothing rendered by the web browser

  • A pop-up dialog box stating that the "Document Contains No Data"

  • A partial document when more is expected

Most of these problems are caused not by a bug in a script, but by a bug in the HTML produced by the script or template. For example, if </table>, </form>, or </frame> closing tags are omitted, a document may not be rendered in some browsers.

An HTML problem can often be identified by viewing the HTML page source using the web browser. For example, on a Linux platform running Mozilla or Netscape, the page source can be accessed with a right-mouse click anywhere over the document and by then selecting View Page Source from the pop-up menu.

For compound or hard-to-identify HTML bugs, the W3C validator at http://validator.w3.org/ analyzes the correctness of the HTML and issues a report. It's an excellent assistant for debugging and final compliance checks before delivery of an application. You can enter the URL of your resource into the W3C validator, or you can upload the HTML output and have it checked. The former is easiest, but the latter is sometimes the only option if your page can't be retrieved from behind a firewall or because a PHP session or authentication is needed to access it.

If you want to upload a page to the validator, the easiest method is to use the Save Page As... menu option in your browser to save the document. Then, upload the saved file by clicking on Browse next to the Local File box at http://validator.w3.org. Remember when using the validator that you need to validate the script under all its different output conditions: for example, if your page can produce a form or display the results of a query in a table, you need to check both scenarios.

If an HTML problem still proves hard to find, and it doesn't use templates, consider adding calls to the flush( ) function after print or printf statements. The flush( ) function empties the output buffer maintained by the PHP engine, sending all currently buffered output to the web server; without flush( ), buffered output usually isn't sent to the browser when an error occurs and the script stops. The function has no effect on buffering at the web server or the web browser, but it does ensure that all data output by the script is available to the web server to be transmitted and rendered by a browser. Remember to remove the flush( ) function calls after debugging, because unnecessary flushing may prevent efficient buffering of output by the PHP scripting engine. Buffering and its use in error reporting is discussed in more detail in Section 12.3.

A common problem that shouldn't be confused with those described here is not receiving a response from the web server and getting a "no response" error message. This problem is a symptom of the bugs described in the next section, and can be distinguished from the problems described here by observing the web browser. Most of the popular graphical browsers show they are waiting for a response by animating the logo in the top-right corner. For the HTML problems described here, the page loading process will be complete, the logo animation will have stopped, and the HTML page source can be viewed through the web browser menus.

12.2.2 Variable Problems

In this section, we discuss problems that cause a page never to arrive at the web browser, or complete pages to appear with missing output from variables. Many of these problems can be avoided if you follow our recommendation to report E_NOTICE errors during development. Variable naming

If you haven't turned on E_NOTICE errors, making a mistake with a variable name sometimes inadvertently creates never-ending loops. The result of a never-ending loop is that one of two problems occurs: first, the web browser eventually times out and alerts the user that the web server isn't responding to an HTTP request; or, second, PHP complains that the maximum script execution time (usually 30 seconds) has been exceeded. Which error you see depends on your configuration: you'll see whichever timeout problem occurs first.

The following loop never ends, and no output is produced:

for($counter=0; $counter<10; $Counter++)

  myFunction( );

The variable $counter is never incremented because $Counter and $counter are different variables. Therefore, $counter is always less than 10. Common bugs result from subtle changes in variable names through changing case, omitting or including underscores, or simple typing errors.

Never-ending loops can also produce unexpected output. The following loop can render thousands of greetings in a web browser in a very short time:

for($counter=0; $Counter<10; $counter++)

  echo "<br>hello";

With error reporting set to detect E_ALL errors (or to a setting that include E_NOTICE), the error is detected. For example, the following fragment:


for($counter=0; $Counter<10; $counter++)

  echo "<br>hello";

produces a never-ending number of notice messages stating:

Notice: Undefined variable: Counter in /usr/local/apache2/htdocs/count.php

 on line 3

The script keeps on running because it's only an E_NOTICE error. You can prevent the endless output of error messages from the same source file and line by changing your php.ini file to include the setting:

ignore_repeated_errors = On

As usual, you need to restart your Apache web server after the change. For the $Counter example, this will ensure one error message but it won't prevent endless greetings. However, this setting can also have the undesirable side-effect that the error will be reported exactly once: if you press reload or refresh, you'll never see the error again! Missing output

If you still haven't turned on E_NOTICE errors, an uninitialized variable can leave you with no output but without an explicit error. This seems obvious, but it can be hard to identify if the problem is a subtle error. Consider this example of a change in case:

$testvariable = "hello";

echo "The value of test is $testVariable";

This produces the string:

The value of test is

If output appears but isn't as expected, an uninitialized variable is a possibility. The simplest approach to detecting the error is then to check for a bug by setting error_reporting(E_ALL) at the top of the script or in your php.ini as discussed in the last section.

A similar problem that can't be detected with PHP errors can also occur when single quotes are used instead of double quotes. As discussed in Chapter 2, the content of single-quoted strings is always output directly, and the string isn't interpreted like a double-quoted string is. For example, consider the fragment:

echo 'the value of test is $test';

This produces:

the value of test is $test

It doesn't output the value of the variable $test.

12.2.3 Less Common Problems

The two problem categories we have outlined so far are the most common mistakes programmers make in PHP. We outline three less common and less PHP-specific problems here. Complaints about headers

Functions that output HTTP headers are discussed in Chapter 5, Chapter 10, and Chapter 11. Such functions include header( ), setcookie( ), and session_start( ). A common problem seen when using these is an error message such as:

Warning: Cannot modify header information - headers already sent by (output started 

at /usr/local/apache2/htdocs/test.php:2) in /usr/local/apache2/htdocs/redirect.php on 

line 3

Headers can be sent only before any HTML is output, and this includes any whitespace at the top of the file. So, for example, if there is a blank line or single space character before the script open tag <?php, HTML has been output (albeit not very interesting HTML) and any function that sends an HTTP header will fail. Fortunately, the error message gives you a hint where to look. In the above example, the location that triggered the error is listed within parentheses, as a filename followed by the line number, which is 2.

It's possible to avoid header problems by altering how PHP buffers data using the output control library functions. We discuss these later in Section 12.3. Missing semicolons, braces, and quotes

Omitting a semicolon at the end of a statement is usually easy to detect. The PHP interpreter continues to parse the script and, when it reaches a threshold of confusion or exceeds the maximum statement length, reports an error one or more lines later that indicates a semicolon has been missed. In most cases, this is easy to fix because the line missing the semicolon is identified in the error message.

However, in some cases, a missing semicolon can be as hard to identify as a missing closing brace or a missing quotation mark. The following erroneous code is missing a closing brace:


for($x=0; $x<100 ;$x++)


  for($y=0; $y<100; $y++) {

    echo "test1";

    for($z=0; $z<100; $z++)

      echo "test2";



The error reported is:

Parse error: parse error, unexpected $ in

 /usr/local/apache2/htdocs/bug.php on line 9

Line 9 is the last line of the script, so the nature and cause of the problem aren't immediately clear. However, parse errors that aren't immediately obvious on the reported line in the error message are usually on the line above, or there may be a missing brace or quotation mark.

It takes only a minute or so to identify the missing brace in this example, but more complex functions can take much longer to fix. This highlights the importance of indentation in code and of avoiding the practice of placing opening braces at the ends of lines. Braces should always be placed on lines of their own and match up vertically with their partner. If you use an editor that has syntax highlighting, this also makes spotting bracket and quotation problems much easier. Source shown in the browser

Missing open and close script tags can cause problems similar to missing quotation marks or braces, but are much easier to identify. If an open script tag is missing, it's obvious because code is displayed in the browser. A missing close tag usually causes a parse error, because the PHP script engine is confused when it tries to parse HTML and interpret it as PHP, or it unexpectedly reaches the end of the file.

If script source is always displayed and never run, it's likely that Apache is misconfigured. Specifically, it's likely that the AddType directive for processing PHP scripts was not added in the Apache installation process; for example, this seems to be the default in some recent Red Hat Linux distributions.

Another possible cause of scripts being displayed and not run is that the PHP scripts aren't saved in files ending with the .php suffix. This problem often occurs with legacy PHP3 code, because PHP3 scripts usually use the .php3 suffix. The problem can be corrected by renaming the script files so they end in the .php suffix or by adding an additional AddType directive to the Apache httpd.conf file:

AddType application/x-httpd-php .php3