Using PDT + xDebug (for debugging Drupal projects)

Submitted by boaz on Wednesday, March 5, 2008.

This blog post is meant to be a short guide and tips repository for setting up a PHP development environment using Eclipse PDT and xDebug. I use such an environment for my Drupal based development and it is an invaluable tool to me.

This post doesn't explain everything because there's lots to it. From my experience (as a former Zend employee (Zend produces its own commercial PHP IDE)) and from my acquaintance with the PHP development community, I have a good reasons to believe this article could serve a few PHP developers out there.
If you have comments about this article please post them! The good thing about CMS is that they let you edit your posts easily even after you've published them wink .

Background

  • One must understand what it means to debug in this article's context and debug PHP applications as it still seems that the most prevalent PHP debugging
    tool is var_dump/var_export/print_r() etc... . Debugging using PDT +xDebug is a whole different ball game. Don't worry - its really not that complicated, but it is different from using textual printing of variables. In fact, many developers are already familiar with debugging tools and concepts from other languages such as breakpoints, stack trace, flow control. This is the concept of debugging we'll see here as well.
  • The advantages of using the debugging concept that is demontrated in this article is that you will be able to excute a PHP application/scripts in a fully controlled manner and have excellent insight on what's going on in the system as the scirpt run: we'll be able to postpone the run in predetermined lines of code ("breakpoints"), carefully see each line of code being executed, the variables that lives in that context and their data (and alter them as well in real time!), and more... . Cool, aint? cool
  • The debugging method we'll explore involves client and server side programs/utilities. The client side is the Eclipse PDT application. It is the controller of the whole "debug session". Most of your day to day debugging work will be conduct via PDT. It contacts and communicates with the server side, as needed. The server side entity is a php extension ('add on') that enables this debugging magic to take place. This is the xDebug extension, which needs to be incorporated into the LAMP/WAMP stack as a PHP extension during the set-up process we'll cover on our next section.

 

xDebug installation

Lets start with server side installation and configuration. xDebug has very good documentation on its web site. Therefore, I'll just give here a bullet list of points that you'll need to cover, without going into details. Those I'll provide with links to the relevant locations in the documentation mentioned.

Lets start:

  • I highly recommend installing your personal development LAMP/WAMP machine. xDebug has a limitation (as far as I know) that it can initiate debug sessions only to one machine and that it needs to be configured in php.ini. This means that your client machine's IP should be present in php.ini (we'll cover that shortly) and it needs to be edited (+web server's restart) every time some other developer wishes to debug on that web server. This is of course not comfortable or even hardly usable in multi-developers-per-WAMP/LAMP environment (this in contrast to commercial debugging tools that enable multiple developers to debug simultaneously against one web server).
    These days its quite easy to setup a LAMP/WAMP on your personal desktop/laptop so the limitation just mentioned is not a blocker. Linux folks would probably install apache/php/mysql with their package management tool and Windows ppl can use XAMPP or the like to install a WAMP (with great ease, I should note; XAMPP is great).
    So, from this point on I will assume that you have your own LAMP/WAMP machine. Lets call it... <drums>the web server!.</drums>
  • Download and install xDebug extension on your web server. The steps to do that are described here: http://xdebug.org/docs/install . After this is performed successfully, you should be able to see the xDebug extension present and kicking when running a phpinfo() on the web server.

    Please note that xDebug can collide with some other extensions such as other debugging extensions. Consult xDebug documents for more info on this... .
  • Now we shall configure the xDebug installation to work properly for our purposes, establishing our own debugging environment. There are a few ini directives that needs to be set up in php.ini. Here too, I'll give a short list of what I know to be working ok and references.
    In your php.ini, put the following after the xDebug extension loading lines (that was configured in previous step):
    • xdebug.remote_mode="req" (this is the default value. not needed. I do it for verbosity)
    • xdebug.remote_enable=On (you want to debug no? smiley...)
    • xdebug.remote_host="192.168.1.3" (this must be configured to your client's IP address)
    • xdebug.remote_port=9000 (this is the default value. You can change it if you want. see important note below).
    • xdebug.remote_handler="dbgp"
  • Important - make sure that if you have a firewall on your client side machine (where PDT will run) it doesn't block incoming TCP connections to the port number configured in debug.remote_port above.
  • For the complete documentation on xDebug php.ini directives have a look here: http://www.xdebug.org/docs/all_settings
  • Don't forget to restart the web server after changes to the values in php.ini... .


Eclipse PDT

Ecliipse PDT "all-in-one" package should be almost-ready-to-debug with xDebug out of the box, but some configuration is still needed:

  • First, obviously, download and install Eclipse PDT, if not already done. I'm not a great expert on the various packages it is provided in, but I think the "all-in-one" is a good choice. Link: http://www.eclipse.org/pdt/
  • Open PDT preferences window -> PHP -> PHP servers. Add your web server's details there. Configure a name and document root for the server:
    configuring php server in PDT screenshot
    You might want to add "path mapping" in the tab that bears this title. This will enable the xDebug extension and the PDT to sing the same song while debugging. What do I mean? Imagine that you have several files named "db_funcs.php" in your project, each contain DB functions for different DB (mysql | postgres...) and each located in a different subdir of the project. The needed file is "included" at run time based on the configuration of the DB you are working against (in some config file). Lets say that you're debugging a specific line in db_funcs.php that lurks in includes/db/mysql/ directory. This means that the xDebug extension and PDT needs to be directory-aware when they refer to files because xDebug is running the file and you should be able to see the exact lines that run flowing in PDT. That's why on certain, not so rare occasions, you'll need to configure this tab. Simple configuration example:
  • PDT -> Window -> preferences -> PHP -> Debug (here. no sub-item) -> PHP debugger should be selected as xDebug:
    PDT xDebug selected screenshot
  • Make sure to configure a browser for your PDT (Preferences -> General -> web browser). I work with Firefox:
    PDT firefox selected screenshot
  • Your PDT should be configured at this point. Lets try to debug something shall we?:

Initiating a debug session
I should point out that the debug session instantiation method described below is what I use currently. Like in the rest of the article, TIMTOWDY and "it works for me"... smiley


  • Open PDT, make sure that your project is opened. I usually close other projects. Not sure what affects will happen if they are kept open (on debugging and on other Eclipse functionality that I use such as search facility).
  • Now, make sure that your workspace files are synced and that they are exactly as those on the project files which lurk on the web server. This is because of the reason already mentioned above (configuring "path mapping" tab in Eclipse PDT configuration above): xDebug will run over the web server's files while PDT will show and use the local workspace files. If the same file has one content on the web server's file system and different content on the PDT workspace - that wont be nice... .
    To achieve this synchronization I use the ESftp plugin for eclipse (information and download available here). Its a very cool plugin which enables sFTP facility in a very convenient way for this purpose - I simply configure for the Eclipse project a "site root" on a remote SFTP connection and then I can sync them with very little effort. After you install ESftp go to the Eclipse project root in the "PHP Explorer", right click -> ESftp tab:
    project eSFTP properties screenshot
    I also configured the general Eclipse key bindings to have Ctrl+U perform a "put file to server and save". This is achieving synchronization perfectly and very fast (on a LAN). Make sure to inspect permissions or other problems on the PDT console view (ESftp console).
  • Plan ahead your debugging session. What section of the code you wish to test? Put breakpoint(s) in the relevant line(s) of code by opening the file in the editor -> double click on line number on a line number where PHP code lies in (I think that trying to put a breakpoint on comment will fail. Sometimes it will, at least). See the blue dot that resulted from this double click? That's a breakpoint. I think that reading some on the Eclipse online help in the PDT section of debugging can't hurt at all (In eclipse PDT itself: Help -> Help contents).
  • Now configure a debug session: open the debug dialog: Run -> Open debug dialog (or the toolbar equivalent) -> PHP web page -> "New luanch configuration" (top left button):
    • Choose server debugger xDebug and the PHP server defined earlier
    • "File" should be set to? I'm not sure here. I'm developing on Drupal. Drupal uses clean URLs and everything goes via index.php so I just put there /Project_root/index.php (use "browser" button to select).
    • Break at first line? I don't need it so I deselect it.
    • URL: I check off "Auto generate" and put here the "clean URL" that I wish to debug. For example: /my_view_url/ .
    • Screenshot:
      debug session configuration screenshot
    • Ready?... (don't close the window just you just configured) See next...
  • Click "debug". Your debug session is starting right now! xDebug is getting the debug request and takes control over the execution of the PHP (that is part of the URL you requested) on the server, negotiating with PDT where, if any, there are any breakpoints it should stop at. The result should open in a browser window, should you defined it like that (in advanced tab of the "debug web page" settings configured above).
  • While the debug session is active, once xDebug hits a breakpoint (as told about them by PDT), it'll stop its execution on those files, in the line number specified. PDT will then automatically open up the "PHP Debug" perspective, with the file where it hit a breakpoint (which it takes from it local workspace files - this is why the "path mapping is important, as mentioned above) opened automatically in the editor, and await further commands:

  • You can see in the editor view, on the line number where it stopped the blue dot and a blue arrow indicating where the current execution flow is waiting for you. You can examine at that point the variables and PHP trace in the various views available in the PHP Debug perspective. If this perspective didn't open up for you, open it manually.
  • What exactly happens during a debug session? How does this client-server communication works in regard to the debug session? Take a look in the sketch below.
  • Controlling the flow of your debug session is done with the buttons in the toolbar or via the menu bar "Run" menu.
    flow control screenshot
    Again, please refer to PDT's online help facility for more info on what each flow control button does exactly and lots more on debugging (Help -> Help contents).
  • While PHP on the server (controlled there by xDebug extension) is awaiting command when its execution flow is halted by PDT, you can click on function names on the "debug" view (top left window, defaultly) in the PHP debug perspective. That can provide you with useful information on which function called other functions up to now and also a complete stack of variables that exists in each function call. The best way to understand this is to try it.
  • Last tip: I usually stay with "debug all pages" in the advanced tab of the "debug web page" settings window explained above. Its comfortable to me: when the current debugged page has finished executing (PHP finished its run, passing over all breakpoints and continuing when we told it to, via PDT's flow control buttons) the debug session remains active and any activity via the browser's window will trigger another debug session. Want to finish the debug session completely? (for now) - click the red button in PDT's "Debug" view (PHP Debug perspective).

 

That's it!
Boaz.

5 comments:

Very good writeup
Anonymous says:
March 12, 2010 at 01:02 am
Boaz, I'm working with an indian developer on a new drupal site and your article is very useful on something similar that we're working on. I'm forwarding this to him. Many thanks! Cheers, Patty
xdebug in .module files stops only at functions
Anonymous says:
February 5, 2010 at 08:19 am
Hi Boaz,

Great tutorial. I trying to get this to work with xampp, eclipse and xdebug, although I have the same problem with the zend debugger.

The debugger steps in and breaks at break points I place at function declarations in my .module files.
The problem is that if I try to "Step into" the functions, the debugger jumps to the next function call, and doesn't allow me to debug the code inside each function.
I guess this is not a limitation of the debugger, but something I configured\doing wrong.

I don't have the same problem with index.php, and the debugger behaves there as expected.

Any suggestions?

Cheers
Zion
You can also...
Boaz says:
June 21, 2009 at 08:18 am
BTW, you can also work directly on your server's file. You can have your project file outside of your workspace (which I think doesn't matter much where you put it - go with the default) and thus have project files that are the same files that Apache runs. This requires no syncing other than hitting the "save" on the edited file.
Indeed, you need to create a project
Boaz says:
June 21, 2009 at 08:15 am
Hi,
Indeed, you need to create a project in PDT. Do *not* make a dummy project. Rather, put your actual PHP application sources in it.
While debugging, PDT needs to be able to open files that the server is telling it that its traversing through, while running code between your break points. Also, how would you create breakpoints in PDT if not on your sources?... . You have to make sure that the sources in PDT and your server files are in sync. Otherwise, PDT might jump to non existing lines when asked by the *server* to show file somefile.php, line 167, while on your version of the file in PDT it will contain only 140 lines... . See my section on eSftp plugin for eclipse for one (convenient) way to sync PDT and server files.
Boaz
Debug session
Anonymous says:
June 21, 2009 at 07:56 am
Hi,

Very informative blog. Many thanks for the guidance. Debugging Drupal using breakpoints will be fun.

I was able to follow you up until the section titled, "Initiating a debug session".

You mentioned in this section: "Open PDT, make sure that your project is opened." << Not sure what you mean by this step.
I don't have any project setup as this is the first time I am running Eclipse on my fresh Drupal and WAMP server...should I create a dummy project ? If so, which folder and what should I specify as my default workspace location?

Here are my local settings:
http://localhost points to the folder
C:\wamp\www which points to my drupal files, which contains the index.php file.

Thanks.
-Anil
anilo@hotmail.com

Leave a Comment

Fields with * are required.