PHP Error Handling and Debugging – Part 1

This article describes the process of testing PHP code.  Using the tips that I will explain can help to decrease the code/test cycle time.

The first thing that you must know in order to plan your code/test process is the environment in which your code will run.

If you have full control of the system, less configuration is required. In this case you can rely on the default settings, and simply need to know where the logs are kept by default. On a typical LAMP (apache) system you can find the log files in /var/log/httpd. Check the documentation for the operating system that you use as some operating systems use a different directory (i.e. one version of Ubuntu uses /var/log/apache2). By default error messages from php will be kept in this directory.

If you are developing on a server where you don’t have access to the default logs, you can configure where your log messages are sent by putting a php.ini file containing the directive

error_log: path_to_log

in the root of the domain.

With this information in mind, we can begin to find code errors.

There are two error types to look for:

  1. parse
  2. runtime

A parse error is the first thing to look for when testing new or modified code. This can be something like a missing semicolon or other grammatical mistake. If a parse error occurs, it will be sent to PHP’s error_log. A simple way to find this kind of error is to load the file directly in a browser (i.e. an AJAX script that would not normally run in a browser could be tested this way for parse errors). With a default PHP installation the parse error will shown on the screen.

Most errors that are encountered are runtime errors. There are two kinds of runtime errors:

  1. exception
  2. functional

The first kind of runtime error happens when a statement or function call that is grammatically correct encounters a unexpected circumstance such as an invalid parameter (i.e. fopen(file_that_doesnt_exist,’r’)). This kind of error can only be seen during an actual run of the code with valid inputs. Opening the file in the browser directly usually will not find it as the inputs will not be those that would typically be encountered. For example opening an AJAX script that relys on the _POST variable for its input will typically not run many of the branches because of the missing _POST variables. To find this error, run the script as it would typically be run and check the error log for errors.

A functional runtime error is when the code runs, doesn’t generate an error, but doesn’t produce the expected outputs. To find this error use one or more of the following techniques:

  • echo/printf
  • error_log
  • try/catch

The simplest way to find errors is by adding echo statements to the code. This method can be somewhat tedious and slower to use than others, but a few well placed echo statements that use print_r to show the value of key return data structures can sometimes quickly illuminate the source of the malfunctioning code. The problem with this method is that because it outputs directly to stdout (the web browser) it is only available if the script can be run in the web browser directly with typical inputs. Many times this is not possible (i.e. for AJAX or cron code).

A more general way of debugging is to use the error_log function instead of echo. With the error_log function you can direct the messages to a file of your choosing with

error_log($message,3,"path/filename")

or to the configured error_log mentioned earlier via

error_log($message)

A bonus when using the error_log() function is that you also get a timestamp for each error logged.

If a runtime error is expected, a try/catch statement should be placed to ignore it or otherwise handle it in a way that doesn’t cause the script to stop abruptly.  This way the script will continue to run and an error will be logged.  This is better because you will know at what section of code the error occurred.  If the blocking error had gone uncaught (in the case of AJAX responder script errors), the calling application might have received a malformed response (parse error).  A try/catch statement is only helpful when a blocking exception occurs, and will not help to debug functional runtime errors.  The structure of this type of code testing is as follows:

try {
 //your new code
 } catch(Exception $E) {
 error_log(E.getMessage());
 }

In this article we have discussed simple code/test cycle techniques for PHP.  Tune in next time for part 2 where we will review using a debugger such as XDebug.

TWiki for a dynamic Company Operations Manual

This article is an overview of the TWiki system with an emphasis on usage as an intranet and Company Operations Manual. A small business can benefit by having such a system in several ways :

  • share knowledge and overlap responsibilities
  • document experience and improve processes
  • identify and facilitate process automation

A Company Operations Manual seeks to codify the processes that the company’s operation depends upon. It must

  • be simple to use/extend
  • be easy to navigate
  • have properties that facilitate improvement and revision
  • allow compartmentalization

TWiki fits each of these needs abundantly. It is by nature a system designed for ease of input. Concepts such as WikiWords and WebNotify allow for quick navigation by facilitating linkages among the various processes and automatically prompting personnel when processes of interest are updated. There are plugins that can keep statistics on how frequently topics are used. This allows identification of processes that would be good candidates for automation (high usage) and those that could be improved or deleted (low usage). TWiki also has built-in support for access control via group membership. This coupled with good design can simply the process of restricting auditors, contractors, and guests to areas of their focus, expertise, or clearance.

In small business there are fewer hands, and the processes and policys must be correspondingly light-weight. A dynamic, intranet-based Company Operations Manual is one way to achieve this necessary business requirement.

Apache 301 redirects using .htaccess without the WordPress redirection loop.

Improving SEO with Apache 301 redirects using .htaccess

When optimizing SEO it is important to set your site to redirect traffic from yourdomain.com and www.domain.com to the same site. Search engines view www.yourdomain.com and yourdomain.com as two different sites and that can cause them to inaccurately attribute inbound links to either one site or the other, but not both. By creating a 301 redirect you cause all traffic from one of the sites to be permanently redirected (moved) to the other site. Listed below are two methods for doing this with Apache web-server.

Using www in the domain. All traffic is directed to www.yourdomain.com

<IfModule mod_rewrite.c>

RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.yourdomain\.com
RewriteRule (.*) http://www.yourdomain.com.us/$1 [R=301,L]

</IfModule>

Using yourdomain.com. All www traffic is directed to yourdomain.com.

<IfModule mod_rewrite.c>

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.yourdomain.com$ [NC]
RewriteRule ^(.*)$ http://yourdomain.com/$1 [R=301,L]

</IfModule>

The WordPress redirection loop

The Problem:

The wordpress redirection loop occurs when you have installed wordpress and configured it in a way that doesn’t match your .htaccess redirect. The case could be that you’ve set up the wordpress installation on www.yourdomain.com and created a 301 redirect to in your .htaccess file to direct all www.yourdomain.com traffic to yourdomain.com. When you attempt to load your website in your browser you will notice that you get an error message informing you that the site is redirecting in a manner that will never be resolved.

To correct it:

  • Remove the 301 redirect from the .htaccess file for your site.
  • Login to your wordpress installation and verify how you set your domain up there (www or not).
    Wordpress Configuration Screen Shot 1
    Wordpress Configuration Screen Shot
    Wordpress Configuration Screen Shot
    Wordpress Configuration Screen Shot 2

  • Rewrite the 301 redirect to match the wordpress installation.  For example if you installed wordpress on yourdomain.com set your .htaccess redirect to direct all www.yourdomain.com to yourdomain.com.

Now your site and wordpress get full credit for inbound links and you are well on you way to maximizing the value of your off page SEO.

I hope this helps you.

Your comments are appreciated.

– Joel