Categories
Articles

Creating a Simple PHP Debug Library


By Lon Hosford
I like to have a plan for debugging from the start. That usually means a debugging library. Debugging libraries can be simple and can be complex.

Blog post icon for Creating a Simple Debugging Library
Blog post icon for Creating a Simple Debugging Library
They can be procedural and they can be object oriented. No matter which approach, having something that is generic to your applications you can drop in is the minimum before coding. In particular a debugging library is handy when you inherit another PHP project where there is no breadcrumb on how testing and debugging was handled.

This is an example of a minimalist framework for a debugging library and testing dashboard. It is great for those first learning to program in PHP. I like to use it for teaching PHP.

There is a lot we can add to the library such as routing log messages to the UI or to a log file of your choice. But you can build these features onto this library by adding constants, functions and if needed global space variables.

Source Files: Download

[iframe https://www.youtube.com/embed/rxdI86JakFU 640 360]

The Debug Common Library – debug_common.inc.php

This is the minimal debug library.

<?php
/**
 *	Debugging configuration.
 *	
 *	Search all source files for **PRODUCTION SETTING** for production settings
 *  @author Lon Hosford 
 *  @link www.lonhosford.com 
 *	@copyright 2014 Alonzo Hosford
 *  @license GPL 
*/
/**
 *	Send runtime errors to stdout(1) vs stderr (0)
 *	**PRODUCTION SETTING** = 0
 */
ini_set('display_errors', 1);
/**
 *	Send startup errors to stdout(1) vs stderr (0)
 *	**PRODUCTION SETTING** = 0
 */
ini_set('display_startup_errors', 1);
/**
 *	PHP levels of error reporting
 *   0 = off
 *   E_ERROR | E_WARNING | E_PARSE = simple running errors
 *   E_ERROR | E_WARNING | E_PARSE | E_NOTICE = E_NOTICE adds uninitialized variables or catch variable name misspellings
 *   -1 or E_ALL = all errors
 *	**PRODUCTION SETTING** = 0
 */
error_reporting(E_ALL);
?>

The first important item to notice is the use of the search tag, **PRODUCTION SETTING**. It is important for documenting code changes necessary for moving code to other environments such as staging, pre-production and production.

 *	**PRODUCTION SETTING** = 0

You use a file search for **PRODUCTION SETTING** and examine the documentation for changing code to necessary values. If you have something different from production you can create other ways such as a separate search tag for each environment or a generic search tag that will document each environment.

Line 15 allows the override to the PHP configuration property display_errors for displaying errors with the PHP output.

ini_set('display_errors', 1);

The PHP ini_set function sets PHP runtime configuration values and takes the name of the configuration property as the first parameter and the value as the second parameter.

In this case any error messages from PHP are included in the output from PHP. This is regardless of the output format. So if it is a web page, the errors are mixed into the page. You may or may not see them as they could be stuck in the page header section. And this also means if the output is JSON, XML, NVP or any format, the errors ride along often spoiling the parser receiving the output.

Line 20 includes any errors that are generated from PHP starting. This is less common on a well tested hosting site running PHP. But I included just in case as if the error is not in your code it may show here.

ini_set('display_startup_errors', 1);

The final item is to filter the category levels of PHP errors. The usual choices are 0 for off and the constant E_ALL for all levels.

error_reporting(E_ALL);

You can include bitwise operations to combine the other constants listed in the comments. You may find that helpful when inheriting code with many errors to filter out key errors to flesh out, third party code or you have created an error that cascaded a multitude of errors. Avoid that latter situation with test often and in small code units.

468X60
Application Common Library – lib_common.inc.php
<?php
/**
 *	Library for common database configuration, data and initalizations.
 *
 *	Include before running other scripts.
 *	Search all files for **PRODUCTION SETTING** for production settings
 *	@author Lon Hosford 
 *  @link www.lonhosford.com 
 *	@copyright 2014 Alonzo Hosford
 *  @license GPL 
 */
/**
 *	Include debugging configuration
 *
 *	@see debug_common.inc.php
 */
include_once "debug_common.inc.php";
/**
 *	Initialize use of session tracking and the PHP $_SESSION var.
 */
session_start();
/**
 *	Set the timezone.
 */
date_default_timezone_set('America/New_York');
/**
 *	Required PHP version
 */
const VERSION_PHP = "5.3.1";
?>

Your PHP applications should have a common code block for application level variables, constants and functions. This could be a singleton OOP class or a simple procedural file.

The main point is to have the first loaded coded here and keep it clean of debugging specific code.

Also this is where I document code search tags used to set values when moving code between environments.

 *	Search all files for **PRODUCTION SETTING** for production settings

The debugging library is hooked into this file as early as possible. Generally you can leave this line of code for other environments but if you want to comment it for those environments, add your search tag in the comments with the instructions for doing that.

include_once "debug_common.inc.php";

[/code]
An advantage to a one line addition of a debugging library is you can have multiple versions of the debugging library and swap them here.

The session_start line has no impact on debugging. It shown as a common first line of code in a common library.

session_start();

Same situation with date_default_timezone_set function. This is just making it clear the server running PHP should use that specific time zone for handling date and time computations.

date_default_timezone_set('America/New_York');

I prefer to include all the constants for library versions in the common application library starting with the PHP version. Here I use VERSION_PHP and just prefix all the version constant names with VERSION_PHP.

const VERSION_PHP = "5.3.1";

You may want similar constants for other libraries such as MySQL, PHPMailer or a PayPal library.

At the minimum you can use these constants in a debug test to see if the versions are correct. Also you can use them in application code to take action if they are not correct.

[ad name=”Google Adsense”]

Debugging and Testing Dashboard – debug_dashboard.php
<?php
/**
 *	The debug library demonstration and testing.
 *
 *  @author Lon Hosford 
 *  @link www.lonhosford.com 
 *	@copyright 2014 Alonzo Hosford
 *  @license GPL 
*/
include_once "lib_common.inc.php";
?>
<!doctype html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Testing and Debugging Dashboard | lonhosford.com</title>
	<style>
	body{ font-family:"Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif}
	pre {
	 white-space: pre-wrap;       /* css-3 */
	 white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
	 white-space: -pre-wrap;      /* Opera 4-6 */
	 white-space: -o-pre-wrap;    /* Opera 7 */
	 word-wrap: break-word;       /* Internet Explorer 5.5+ */
	}
	.mono-space{font-family:monospace;}
	table,td {border:solid 1px #000;}
	</style>
</head>
<body>
<h2>Testing and Debugging Dashboard </h2>
<h4><a href="<?php echo $_SERVER['PHP_SELF'];?>"><?php echo basename(__FILE__);?></a></h4>
<hr>
<pre>
<?php 
echo "PHP Version Required: " . VERSION_PHP . "\n";
echo "PHP Version Detected: " . phpversion() . "\n";
echo "PHP Version is <strong>" . (version_compare(phpversion(), VERSION_PHP, '>=') ? "": "IN") . "VALID</strong>." . "\n";
echo "Display date/time: " .  date('m/d/Y h:i:s a', time()) . "\n";
echo "Display display_errors: " . ini_get("display_errors") . "\n";
echo "Display display_startup_errors: " . ini_get("display_startup_errors") . "\n";
echo "Display error_reporting(): " . error_reporting() . "\n";
?>
</pre>
</body>
</html>

This last file is really a simple testing and debugging script. There are various levels of sophistication for testing in all programming languages.

At the minimum, you should have a script or scripts that can run independently from your application, which means these scripts are loaded separately, and perform tests. If you an automate them, the better. They will include your code of course and by doing so you will start on your way to unit testing or at least testing smaller parts of your code and thus forced to write your code in more modular units.

I did not include any examples of testing application code here, but there is a hint of a permutation in the video. I often have several files all included into this file. The separate files target testing a specific part of the code. All tests lean towards unit testing.

Also this is a great place for general debugging information.

Here I am showing the PHP version,

echo "PHP Version Required: " . VERSION_PHP . "\n";
echo "PHP Version Detected: " . phpversion() . "\n";
echo "PHP Version is <strong>" . (version_compare(phpversion(), VERSION_PHP, '>=') ? "": "IN") . "VALID</strong>." . "\n";

timezone information.

echo "Display date/time: " .  date('m/d/Y h:i:s a', time()) . "\n";

and debugging library settings.

echo "Display display_errors: " . ini_get("display_errors") . "\n";
echo "Display display_startup_errors: " . ini_get("display_startup_errors") . "\n";
echo "Display error_reporting(): " . error_reporting() . "\n";
?>

In the end, the running of this script highlights key settings that everyone scrambles to check before or worse after moving code to another environment. So running this script becomes a check list item before making those moves.

[ad name=”Google Adsense”]