Debug PHP with Xdebug, only when you ask

On this page

Turn Xdebug on for a PHP version on the Runtimes screen. The first time, Short Leash builds Xdebug for that version, which takes a minute. The PHP 8.6 preview has no Xdebug yet: its switch says Not available for previews yet.

Only requests that ask for it

With Xdebug on, Short Leash starts a second PHP pool for that version with Xdebug loaded. Requests go to it only when they ask for a debug session; every other request keeps using the normal pool, so your sites stay fast.

A request asks for a session with any of these:

  • an XDEBUG_SESSION or XDEBUG_TRIGGER cookie (set by the Xdebug browser extension, or by your editor)
  • XDEBUG_SESSION_START, XDEBUG_TRIGGER or XDEBUG_PROFILE in the query string

While PhpStorm has breakpoints in a site's project, every request to that site gets a session too: see Breakpoints from PhpStorm.

Your editor

Xdebug connects to your editor on 127.0.0.1:9003. In PhpStorm, start listening for debug connections; in VS Code, start a "Listen for Xdebug" launch configuration.

Each session starts in Short Leash's small prepend file before your code. PhpStorm's Force break at first line when a script is outside the project (Settings › PHP › Debug) would stop there; turn it off.

Runtimes › Xdebug settings changes the port and the modes (debug and develop by default; add coverage, profile or trace when you need them).

Breakpoints from PhpStorm

While Xdebug is on for a site's PHP version, Short Leash also starts a debug session for requests that don't ask for one when PhpStorm has enabled line breakpoints in the project, so you don't need a browser extension. This is on for every PHP site; to leave a site out, turn off Debug when PhpStorm has breakpoints under Debugging on its Site settings, which also shows how many breakpoints Short Leash counts.

PhpStorm saves breakpoints when you press ⌘S (Ctrl+S on Windows) or close the project. Press ⌘S after adding or removing a breakpoint. Until you do, Short Leash sees the breakpoints PhpStorm saved last; once saved, they reach Short Leash within a couple of seconds.

While breakpoints are set, every request to the site uses the slower Xdebug pool, even with PhpStorm closed. Xdebug's "Could not connect to debugging client" line, which it writes on each of those requests while nothing listens, is left out of Short Leash's logs, the PHP pool's under Logs included. To go back, remove or disable the breakpoints and press ⌘S, or turn off Debug when PhpStorm has breakpoints.

Requests Short Leash sends to Xdebug this way carry XDEBUG_SESSION=PHPSTORM, which tells Xdebug to start. Your code sees it in $_SERVER and getenv(), but not in $_GET or $_COOKIE.

Short Leash reads the file just after a request, never during it, so the first request after Short Leash starts, or after 10 minutes without requests to the site, may not stop at a breakpoint. Reload the page and the next request will.

What Short Leash reads

  • Only <site>/.idea/workspace.xml, the .idea folder at the site's root. Short Leash never changes it, and doesn't read it when .idea or the file is a symlink.
  • Only the enabled PHP line breakpoints in its XDebuggerManager part. JavaScript and exception breakpoints don't count, and neither do disabled ones.
  • Only while Xdebug is on for the site's PHP version and the site's switch is on. Otherwise Short Leash doesn't open the file at all.

Outside an import you start, Short Leash doesn't read other apps' files; this exception is recorded in ADR 0079, on importing from other tools and reading PhpStorm's breakpoints.

What isn't covered

  • Laravel Octane sites.
  • Projects in the older .ipr format, which keep their breakpoints elsewhere.
  • Projects PhpStorm opens in a container, over SSH or through remote development, which keep their workspace on the other side.
  • Mute Breakpoints in PhpStorm: Short Leash can't see it, so requests still use the Xdebug pool. Turn off the site's switch instead.

Command-line scripts

With Also for Artisan, queue workers and tests Short Leash runs on, leash php and the processes Short Leash runs load Xdebug too. They connect to your editor only when started with XDEBUG_SESSION=1:

Terminal window
XDEBUG_SESSION=1 leash php artisan my:command