Debugging PHP with IntelliJ IDEA

April 26th 2019 IntelliJ IDEA PHP Debugging

I haven't done much PHP development, but occasionally I still need to read or write some PHP code. The latest reason for this was a CMS site for a local community organization I'm administering. I was asked to modify its template to show a different logo based on where in the sitemap the current page is located. How hard could it be?

The CMS is running on an older version of CMSimple_XH. I've done some minor customizations for it in the past, but didn't have any idea how to determine the position of the current page in the sitemap. After some consideration, I determined that the best starting point would be the code for the navigation breadcrumbs. I was somewhat disappointed when I found the code:

function locator() {
  global $title, $h, $s, $f, $c, $l, $tx, $txc, $cf;
  if (hide($s) && $cf['show_hidden']['path_locator'] != 'true')
    return $h[$s];
  if ($title != '' && (!isset($h[$s]) || $h[$s] != $title))
    return $title;
  $t = '';
  if ($s == 0)
    return $h[$s];
  elseif ($f != '')
    return ucfirst($f);
  elseif ($s > 0) {
    $tl = $l[$s];
    if ($tl > 1) {
      for ($i = $s - 1; $i >= 0; $i--) {
        if ($l[$i] < $tl) {
          $t = a($i, '') . $h[$i] . '</a> &gt; ' . $t;
          $tl--;
        }
        if ($tl < 2)
          break;
      }
    }
    if ($cf['locator']['show_homepage'] == 'true') {
      return a(0, '') . $tx['locator']['home'] . '</a> &gt; ' . $t . $h[$s];
    } else {
      return $t . $h[$s];
    }
  }
  else
    return '&nbsp;';
}

I spent some time trying to understand what the code was doing but I didn't seem to make any progress. Then it dawned on me: inspecting the code with a debugger could provide the insight necessary to understand this code and implement the requested feature.

I was already using IntelliJ IDEA Ultimate with the PHP plugin for editing the code (providing the same feature set as the specialized PhpStorm IDE). Of course, it also supports debugging. However, it does require some setup before you can start using it. I didn't seem to have much choice, so I decided to give it a go. Fortunately, the documentation is very well written so that even an almost complete beginner in PHP like me can get it working in a reasonable amount of time. Still, I had to overcome some difficulties along the way. I decided to document them in this blog post for future reference.

First, I had to install the correct version of Zend Debugger for the PHP interpreter I was using. I installed PHP on my development machine a while back and haven't touched it since. The best way to learn about PHP interpreter in use is to call the phpinfo function. As it turned out, CMSimple_XH has a page with the phpinfo output in the admin section. This was enough to determine the version and architecture and install a matching version of Zend Debugger.

Next, I needed to modify the php.ini file to tell PHP about the debugger I installed. Again, i looked at the phpinfo output to find the file (it was C:\Program Files (x86)\PHP\v5.6\php.ini in my case). I simply copied the settings from IntelliJ IDEA documentation and specified a port. Since I wasn't sure whether I had the thread-safe or the non thread-safe version of PHP installed, I added both settings:

zend_extension="c:\Program Files (x86)\PHP\v5.6\ZendDebugger.dll"
zend_extension_ts="c:\Program Files (x86)\PHP\v5.6\ZendDebugger.dll"
zend_debugger.allow_hosts=127.0.0.1
zend_debugger.expose_remotely=allowed_hosts
zend_debugger.tunnel_min_port=9000
zend_debugger.tunnel_max_port=9000

After restarting IIS, I could confirm that there was now a Zend Debugger section in the phpinfo output. I was on a good path.

It was time to configure IntelliJ IDEA. In the Settings dialog, I navigated to Languages & Frameworks > PHP > Debug and set the Debug port for Zend Debugger there to match the value in php.ini. Then I clicked the Validate link in the Pre-configuration section to check the configuration. I set the local path to my PHP application and the IIS-served URL to it and then clicked Validate. Success:

Validate Debugger Configuration on Web Server

Only one last step remained: installing Zend Debugger Toolbar extension for Chrome. This is required to start debugging because in contrast to most other development frameworks, the Zend Debugger will connect to IntelliJ IDEA (after receiving specific cookies in the browser request) and not the other way around.

To debug a specific request, I followed these steps:

  1. In IntelliJ IDEA, set the breakpoint at the point of interest in the code.
  2. Also in IntelliJ IDEA, click Run > Start Listening for PHP Debug Connections (there's also a corresponding button in the toolbar to the left of the Stop button).
  3. In Chrome, click on the Zend Debugger Toolbar extension button and select one of the options, e.g. Debug All Pages.
  4. Navigate to the page of interest in the browser. In IntelliJ IDEA, the execution will stop at the breakpoint.
  5. Proceed with debugging like in any other language.

Being able to inspect the values of variables in the above block of code and follow the code execution for a couple of pages in the sitemap helped me tremendously with understanding the code. I was soon able to implement the requested modification. Having the right development tool can often be a huge timesaver.

Copyright
Creative Commons License