Ever since I started using Drupal in October 2005 I wanted to be able to walk the code and debug quickly and efficiently. There is only so much you can do with drupal_set_message and dprint_r statements, so I looked around and decided to try Activestate Komodo. I hit a few problems along the way in configuring my Mac, I think a previous evalulation copy of Zend IDE and my relative newness to OS X were the problem. But with some background reading, and some help from JeffG at Activestate I got everything working nicely.
Overview
Let's look at the whole picture of what we are trying to do and what software we will be using to achieve our aim of debugging Drupal. For simplicity I am going to assume we are going to use a local web server and debug locally on the same machine.
- Web server. I'm using Apache 1.3.33
- PHP 4.3.11 with Xdebug v2.0.0
- Activestate Komodo
To do this on OS X, the easiest way is to download the Apache 1.3 / PHP 4.3.11 installer package from entropy.ch as the standard version that comes with Tiger does not work.
Installation
There are a number of steps to ensuring we get all the applications communicating with each other.
- Download and install the Apache 1.3 / PHP 4.3.11 installer package from entropy.ch
- Download and install Activestate Komodo, (you can get a 30-day version so you can try before you buy). I am using version 3.5 personal edition.
- Run Komodo.
- Select Komodo → preferences from the menu
- Expand the Languages Category on the left of the dialog box, and select PHP. You should now see something like the following:
PHP Preferences in Komodo
Now we need to ensure we are using the correct php, and that we select this as the Default PHP Interpreter. So at the terminal check what php is being picked up in the path using the which command, then find out what php version we're using and whether it has Xdebug.
Now Path to alternative PHP configuration file is where we'll store a php.ini and Xdebug library so specify somewhere under your home directory. The php.ini file will contain debug variables defining how we want to debug. I created a Komodo directory and a debug subdirectory to it to store mine.
Let's click on the Debugger Config Wizard button and setup the debugger.
Activestate Komodo Debugger Configuration Wizard
Let's run through the wizard.
Initial screen of the debugger wizard.
Click continue.
Select the php to use in Installations found on your system field, this should be the one which has Xdebug.
Again for Setup this installation you should have the same value as the other selected field in this dialog.
Click the Continue button. Now in the next screen the INI file to be copied should be from a path below where the selected php executable is, while the Put debug version of ini at should be set to a directory somewhere below your home directory.
Click the Continue button. The next screen asks us where our extensions directory is. The path here should be the same path as that specified in the previous screen under the Put debug version of ini at field.
Click the Continue button. Here we can review the settings we have entered, and then click the Continue button.
Finally we are informed that we have finished the installation.
Now we just need to see what it has created and whether it works.
Checking the configuration
Let's see if it works. There is a utility on the Start Page of Komodo for doing this, however we will also look at the php.ini file that the wizard created and add a few more parameters to get it all working.
To start with, we can use the Check Configuration feature on the Komodo Start Page:
Click on the Check Configuration link and if all is well you should see something like the following:
Now we should look at the php.ini file created by the wizard. So load it up in your favourite editor.
Here we can see what the wizard added. I found in my version of Komodo that the remote_host and ide_key values were not defined so I added them. My configuration did not seem to work without them. You may find similar problems and may need to change your remote_host to 127.0.0.1
One final test would be to do a phpinfo test in your web browser and ensure you can see Xdebug defined in the resulting page. If you cannot then php is not configured correctly. From the command line a php -m will show the compiled modules, and if your path is picking up the correct php then you should see Xdebug listed under a [Zend Modules] section of the output.
Ok, now the moment of truth, let's try to debug something...
Invoking the debugger
There are two ways to invoke the debugger.
- Add &XDEBUG_SESSION_START=userid to the URL.
- Add xdebug_break() php function to your code.
The first method is also the easiest. Simply, navigate to the page you wish to debug, append the &XDEBUG_SESSION_START=userid where userid is your user name, sp in my case I substitute userid with bpretsel, hit the browser refresh button and then the Komodo should start debugging. Switch to Komodo, also check that the listener has detected the call to debug.
Now, if it does not work then the problem may be one of the following:
- Hostname is not correctly configured, i.e. you may have 127.0.0.1 instead of localhost. Change this in your php.ini file. If you are going to dabble with this file it may help to comment out lines rather than delete so that you can keep track of previous values you specified.
- Listener on Komodo may not be running. In Komodo, select Debug → Listener Status to view the status and what port the listener is using.
- Port number of config and listener are different. Port in php.ini and Komodo Debug Listener should be 9000.
- Your apache httpd.conf may provide some clues. You can locate yours using httpd -V look for the SERVER_CONFIG_FILE line to locate the file.
Tour of the debugger features.
Once the excitement of getting the debugger to work dies down, you'll want to know what features are available to make your life debugging Drupal easier. The following pages give you a flavour of those features with examples of usiing them with Drupal.
Common commands in a debugger
The following commands are common in most debuggers, and anyone who has used a debugger in another language, e.g. C, Perl will feel at home.
These are reading from left to right: Step In , Step Over, Step Out, Go/Continue, break now, Stop, Detach
Step In
This will follow the code, so that if you step into a line containing a require statement or a function call, pressing this button will cause the debugger to go to the include file for a require statement, or the file containing the function definition for function calls.
Step Over
This will not follow the code, it will step over to the next line to execute. This is the most common action, and certainly you'd generally want to step over require statements.
Step Out
Allows you to step out of a function or include file. Useful if you accidentally stepped into something or you've seen enough and want to return to where the include file or function was called from.
Go/Continue
Usually you would use this one if you have some breakpoints set up. Under such circumstances you want to let the debugger continue execution as you know the debugger will halt when the next break point is reached.
Stop
Stop debugging. You may have seen enough to know the case of your problem or you are just fed up!
Detach
Stop the debugging process, but instead of stopping continue execution of the program.
Break Time!
Going through every line of code is not the most efficient way to debug, sooner than than later you'll want to start debugging at a particular line in a file or function, eventually with practice you'll be wanting to start debugging when certain criteria has been met.
Load the file you want to debug, if it is not already loaded in Komodo.
Once loaded You will notice we can see a nice navigation window on the left, and below this Komodo displays the currently selected function's comments. This is useful for navigating the Drupal code. Here is a custom module I wrote, in the navigator window.
The easiest way to add a breakpoint is to click on the grey area to the left of the text editor window. This will create a red breakpoint. Click it again and it becomes a red circle filled white to denote the break point is still there but the debugger will not break at that line. Click it once more to delete it, and once more again to reinstate the breakpoint.
Control-mouseclick or click and hold over a breakpoint in the breakpoint tab page will bring up a menu which alls us to set more properties for the breakpoint. Select Properties
Having selected Properties the following dialog window will appear. Now we can make our break point a conditional breakpoint so that we only break whenever our condition is true.
Here we have set a condition to only break if the $op is ever equal to the value 'load'. Of course we could have just set a break point within the case 'load' to achieve the same thing.
Click OK and now you will see the conditional setting display in the Breakpoints tabpage.
Once you get the hang of the breakpoints you will be able to control exactly when you break.
Variables and their values
Drupal has some pretty big nested data structures, so this feature is a nice way to see those values. Click on the Locals tabpage.
Arrays can be expanded/collapsed by clicking on the triangles. This makes it alot easier to navigate the local variables.
Also these variables can be changed by clicking on a variable, then clicking on the pencil icon, or by pulling up the context menu, by either ctrl-clicking or click and hold on a variable.
Watch it!
Watching variables is a common task programmers wish to employ when debugging. Usually the scenairo is that you want to know why a certain variable gets a certain value.
To add a variable to the watch list, first select the Watch tab on the bottom left of Komodo. Now click the square dotted icon with the yellow highlight on the top left of it. This will bring up the following dialog. In here type the variable name you wish to add to the watch list.
Now we can debug as normal, I've added a breakpoint just after the $return variable gets set.
After clicking the Go/Continue debugger command button, the execution breaks at the next break point. Whenever any of our watched variables get changed, the watch window updates. So here we can now see the current value of $return.
But that is not all. With Watch we can change the value of a watched variable thus changing how the rest of the program will execute. To do this click on the variable in the Watch window, then click on the pencil icon. (It is the one to the left of the add watch variable icon).
Watch is useful though its features are covered by the
Locals and
Globals tabs, however sometimes you just want to focus on a small subset of variables so watching just the one you are interested in is alot easier than having to watch the whole set of variables in your program.
Call Stack
a Call Stack is a special stack which stores information about the functions/subroutines in a computer program which are currently being executed. It is a stack because when one function calls another, rather than simply jumping to another part of the program.
We can see a call stack in Komodo. Clicking on entries in the Call Stack will cause the text editor section to jump to that particular function definition.
Here we can see that the main section in file index.php at line 15 called the function menu_execute_active_handler in file menu.inc at line 396. The Call Stack helps you to follow the flow of execution of the program.
Browse Drupal functions
Komodo is a good way to browse the php code, and functions in particular.
Then when you click on function, you can view the comments for that function. Notice the search form, typing in part of the function name will filter the window to only show functions which contain the search text. Here I typed 'cache'...
Also double clicking on a function in the view on the left of Komodo will make the text editor part on the right jump to that function definition.
Removing the breaks, stop debugging and detaching.
To remove breakpoints , view the current breakpoints in the Breakpoints tabpage. Click on the breakpoint you wish to remove and then click on the red circle icon with a black cross. To delete all breakpoints click on the icon with two red circles and a black cross. To toggle whether a breakpoint is active or not, click on the icon with the red and white circle.
To Stop Debugging, Click on the dark blue square on the right hand side in the Debug tabpage.
To detach debugging, i.e. continue execution but not in debug mode, click on the dark blue square with an arrow pointing out to the right.