Debugging PHP in Vim using VimDebugger

August 5, 2010 9 Comments by Richard

Remote Debugging PHP from vim

I’ve recently been using PHP a lot.  I’ve also been using VIM a lot.  So, it makes sense that I would start using the PHP remote debugger, right?  Well, the problem is (and don’t take this the wrong way), the php remote debugger plugin for vim was written in 2004, and there are a few things missing from it.  So, being the overly-easily-amused developer I am, I embarked on a quest to fix it.

DBGp python library

It didn’t take me long to realize that the python classes (vimscript doesn’t do sockets, so you have to use something like python) provided with the old plugin was not extensible enough for what I needed.  I started re-factoring it, but fortunately before I got too far I found a DBGp python library written by ActiveState.  I had to do some hacking to get it all working together — vim doesn’t deal with import statements in python well — but it turned out to be perfect for my needs.

VimDebugger README

Here is the README from the github repo:

Vim Debugger

VimDebugger is a dbgp client plugin for vim for debugging php applications with xdebug. It is currently in early stages, but is already much more advanced than many other options.

Special Thanks

VimDebugger utilizes the ActiveState DBGp library. VimDebugger borrows code liberally from the remote PHP debugger vim plugin by Seung Woo Shin.


At present, must be saved as $VIMRUNTIME.”/plugin/” in order to work correctly. I hope to allow more flexible placement of this file in a future release. VimDebugger.vim should generally be placed in the same directory.

Remote Debugging

VimDebugger will listen on localhost:9000. This could be changed in VimDebugger.vim, but currently is not easily configurable through your .vimrc. You need to have xdebug already configured to connect to that port.

Debugger functions

The following commands are added by the debugger for all your remote debugging needs:

  • :DbgRun – Starts the listener (listens for 10 seconds) if your script is not already attached. If it is, continues (will run to the end or until the next breakpoint)
  • :DbgDetach – Detaches the remote debugger and shuts down the listener
  • :DbgToggleBreakpoint – Toggles a breakpoint on the current line of the current file
  • :DbgStepInto – Steps into the next function or include
  • :DbgStepOver – Steps over the next function or include
  • :DbgStepOut – Steps out to the next step up in the stack

Key Bindings

The debugger does not automatically bind any hotkeys, but leaves that to you to do in your own .vimrc. I often use Visual Studio, so I set my key bindings up in a similar way:

map <F11> :DbgStepInto<CR>
map <F10> :DbgStepOver<CR>
map <S-F11> :DbgStepOut<CR>
map <F5> :DbgRun<CR>
map <S-F5> :DbgDetach<CR>
map <F8> :DbgToggleBreakpoint<CR>


Currently, there are no functions for adding your own watch items, but that is planned for one of the next releases. For now, the watch window will automatically refresh every step with the current context. The Watch window utilizes vim code folding on multi-line entries, so if you have an object, be sure to expand it by double clicking, hitting enter, or using the vim code folding keyboard commands to see the introspection at work. Only three levels are returned, to keep the response from overwhelming the debugger.

For objects, a list of the methods available on that object will be returned with their visibility. Also, a list of properties will be returned with their visibility and their value.

For arrays, a list of values (up to three nested levels) will be returned.


The stack window updates every frame. To go to another part of the stack, simply go to the line in question and double click or press enter.


How well does it work?  Well, let me show you some screenshots, and then you decide.

On the left, you see the code window; that looks almost identical to the old vim plugin.  That’s one thing it did very well, and I couldn’t improve on it; so I shamelessly stole a lot of the code, instead.  On the bottom right you see the first of the improvements I added.  Instead of just displaying a list of stack entries and requiring someone to type “:Up” and “:Dn” to traverse the stack, the list is formatted and set up so that you can double click or press enter on the line you want, and it will take you there in the left pane.

The real improvements can be seen in the watch window, on the top right.  You may notice that these are folded; there are three variables in the local scope, and as you can see they are all instances of objects.  Well, often when I’m debugging I need to know what kind of object that is!  Here it tells you.  That’s not even the best part, though; expand the fold, and you’ll see the following:

The number of methods and properties!  Expand methods:

I’ve truncated it for brevity, but trust me: the method names are all there.  Let’s look at properties.

You’ll notice again; all of the properties, with their values, and… more folds?  Open one of them.

As you can see, array values are also sent.  For practical reasons, there is a depth limit of 3 when fetching watch variables, but that is configurable.  The main challenge is getting the data back from PHP; I have the max data size set at 64KB, so that is the limit to how much can be sent. We could probably raise that limit, but that has other consequences.

Installing it

First, you may want to read this blog post to see how to set up xdebug.  Instead of using the vim plugin they link to, though, get mine from the github repo.  Put and VimDebugger.vim in your ~/.vim/plugins dir, and add the key bindings to your .vimrc.  Let me know how it goes!


  1. Brocchini
    11 years ago

    Hi, tried your plugin with Vim 7.3 and Python 2.7 but as soon as I start vim it gives the following error:
    Error detected while processing function 11_VimDebuggerLoad:
    line 2:
    E117: Unknown function: 11_VimDebuggerInit
    Error detected while processing function DefPython:
    line 549:
    Traceback (most recent call last):
    File “”, line 546, in
    File “”, line 396, in __init__
    NameError: global name ‘VimDebugger’ is not defined

    Could you please help?

  2. taxilian
    11 years ago

    yeah, there was a recent update that seems to have broken it; we’ll try to get that fixed shortly and I’ll post back when it is fixed.

  3. Ben
    11 years ago

    A pull request has been opened to address this issue.

  4. taxilian
    11 years ago

    I think this is fixed now.

  5. Michael Graham
    11 years ago

    I find that when I step into/over/out of code, the code window jumps all over the place, displaying a bunch of other files before going to the next line.  This didn’t happen with debugger.vim.

    Also after every step, the watch window doesn’t update with new data.  The only way to get it to update is to add a new watch expression.

  6. Hugoestr
    11 years ago

    Hey, I just installed it, with the same configuration as the original poster, and I got the same error, with the lines a bit off.

  7. Hugoestr
    11 years ago

    I just fixed it on my computer, and it may be an issue just on my computer. I had to move the line with the following command

    call s:VimDebuggerLoad()

    under the function declarations. It seems that it didn’t like it that s:VimDebuggerInit() wasn’t declared when it was called.


  8. Tobias Sjösten
    11 years ago

    This is so much nicer than the older “dbgd-client” plugin. Thanks for sharing it!

  9. Autonymous
    11 years ago

    Seconding this; I’m also receiving an ‘Asynchronous commands are not supported’ error; I’m running Python 2.6.6, so it may be version dependent.

Post a Comment

Your email is never published or shared. Required fields are marked *