Client 2 - Adding Error Checking

You've seen that PHP will simply dump error messages into the output stream sent to the web browser. That makes it easy to debug PHP scripts, but it's not particularly kind to your users.

There are two error messages displayed in Figure 15.4. The first error occurs when you call the pg_connect() function. Notice that the error message includes the name of the script that was running at the time the error occurred. In this case, my_connect_ pg.php encountered an error on line 9?that's the call to pg_connect(). The second error message comes from line 13 of client1b.php, where you try to use the database handle returned by my_connect_pg(). When the first error occurred, pg_connect() returned an invalid handle and my_connect_pg() returned that value to the caller.

Listing 15.7 shows a new version of the client script that intercepts both error messages.

Listing 15.7 client2a.php

 1 <?php

 2   //Filename: client2a.php


 4   include( "secure/my_connect_pg.php" );


 6   $db_handle = @my_connect_pg( "movies" );


 8   echo "<HTML>\n";

 9   echo   "<HEAD>\n";

10   echo     "<TITLE>client1b</TITLE>\n";

11   echo   "<BODY>\n";

12   echo     "<CENTER>";


14   if( $db_handle == FALSE )

15     echo "Sorry, can't connect to the movies database";

16   else

17     echo "Connected to " . pg_dbname( $db_handle );


19   echo     "</CENTER>\n";

20   echo   "</BODY>\n";

21   echo "</HTML>";

22 ?>

If you compare this script with client1b.php, you'll see that they are very similar. The first change is at line 6?I've added a @ character in front of the call to my_connect_pg(). The @ character turns off error reporting for the expression that follows. The next change is at line 14. Rather than blindly using the database handle returned by my_connect_pg(), you first ensure that it is a valid handle. pg_connect() (and therefore my_connect_pg()) will return FALSE to indicate that a connection could not be established. If you find that $db_handle is FALSE, you display a friendly error message; otherwise, you display the name of the database to which you are connected (see Figure 15.5).

Figure 15.5. A friendlier error message.


This looks much nicer, but now we've lost the details that we need to debug connection problems. What we really want is a friendly error message for the user, but details for the administrator.

You can achieve this using a custom-written error handler. Listing 15.8 shows a custom error handler that emails the text of any error messages to your administrator.

Listing 15.8 my_error_handler.php

 1 <?php


 3   // Filename: my_handler.php


 5   function my_handler( $errno, $errmsg, $fname, $lineno, $context )

 6   {

 7     $dt =



10     $err_txt  = "At " . date("Y-m-d H:i:s (T)");

11     $err_txt .= " an error occurred at line " . $lineno;

12     $err_txt .= " of file " . $fname . "\n\n";

13     $err_txt .= "The text of the error message is:\n";

14     $err_txt .= $errmsg;


16     main( "", " Website error", $err_txt );

17   }

18 ?>

In a moment, you'll modify the client2a.php script so that it installs this error handler before connecting to PostgreSQL.

An error handler function is called whenever a PHP script encounters an error. The default error handler writes error messages into the output stream sent to the web browser. The custom error handler builds an email message from the various error message components and then uses PHP's mail() function to send the error to an address of your choice.

Now, let's modify the client so that it uses my_handler() (see Listing 15.9).

Listing 15.9 client2b.php

 1 <?php

 2   //Filename: client2b.php


 4   include( "secure/my_connect_pg.php" );

 5   include( "my_handler.php" );


 7   set_error_handler( "my_handler" );


 9   $db_handle = my_connect_pg( "movies" );


11   echo "<HTML>\n";

12   echo   "<HEAD>\n";

13   echo     "<TITLE>client2b</TITLE>\n";

14   echo   "<BODY>\n";

15   echo     "<CENTER>";


17   if( $db_handle == FALSE )

18     echo "Sorry, can't connect to the movies database";

19   else

20     echo "Connected to " . pg_dbname( $db_handle );


22   echo     "</CENTER>\n";

23   echo   "</BODY>\n";

24   echo "</HTML>";


26   restore_error_handler();

27 ?>

You've made four minor changes to client2a.php. First, you include() my_handler.php. Next, you call set_error_handler() to direct PHP to call my_handler() rather than the default error handler (see line 7). Third, you've removed the @ from the call to my_connect_pg()?you want errors to be reported now; you just want them reported through my_handler(). Finally, at line 26, you restore the default error handler (because this is the last statement in your script, this isn't strictly required).

Now, if you run client2b.php, you'll see a user-friendly error message, and you should get a piece of email similar to this:

From daemon  Sat Jan 12 09:15:59 2002

Date: Sat, 12 Jan 2002 09:15:59 -0400

From: daemon <daemon@davinci>


Subject: Website error

At 2002-02-12 09:15:59 (EDT) an error occurred at line 9

of file /usr/local/php/secure/my_connect_pg.php

The text of the error message is:

   pg_connect() unable to connect to PostgreSQL server: could

   not connect to server: No such file or directory

   Is the server running locally and accepting

   connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

Now, you know how to suppress error messages (using the @ operator) and how to intercept them with your own error handler.

In the remaining samples in this chapter, I will omit most error handling code so that you can see any error messages in your web browser; that should make debugging a little easier.

Now, it's time to move on to the next topic?query processing.

    Part II: Programming with PostgreSQL