Skip to content
Skills Library
Programming · Analysis

php-debugging

/php-debugging

Use when debugging PHP with Xdebug — breakpoints, step-through, dual-container setup, IDE configuration, header-based routing — even when the user just says 'why does this blow up on request X'.

Licence
MIT
Last repository change
26.10.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
2
Deprecation

No signals detected. Repository changed on 26.10.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Use when debugging PHP with Xdebug — breakpoints, step-through, dual-container setup, IDE configuration, header-based routing — even when the user just says 'why does this blow up on request X'.

Triggers from the description

why does this blow up on request X
Original author description

Use when debugging PHP with Xdebug — breakpoints, step-through, dual-container setup, IDE configuration, header-based routing — even when the user just says 'why does this blow up on request X'.

How it works

  1. When to use
  2. Procedure: Debug with Xdebug
  3. Dual-container architecture
  4. Xdebug configuration
  5. IDE setup
  6. Debugging workflow
  7. CLI debugging (Artisan commands, tests)
  8. Troubleshooting
  9. Container management
  10. What NOT to do
Original SKILL.md headings · 225 lines, 1,152 words
SKILL.md preview
---
model_tier: high
name: php-debugging
description: "Use when debugging PHP with Xdebug — breakpoints, step-through, dual-container setup, IDE configuration, header-based routing — even when the user just says 'why does this blow up on request X'."
domain: engineering
workspaces:
  - engineering
packs:
  - php
trust:
  level: professional
install:
  default: false
  removable: true
---

# php-debugging

## When to use

Use this skill when:
- Setting up or troubleshooting Xdebug
- Debugging PHP code with breakpoints
- Investigating performance issues
- Running code coverage
- Helping users configure their IDE for debugging

This skill extends `php-coder` and `php`.

## Procedure: Debug with Xdebug

1. **Detect the project's debug setup** — check `docker-compose.yml` / `compose.yaml` for Xdebug containers.
2. **Check Dockerfile** — look for a `dev-xdebug` build stage or Xdebug installation.
3. **Check NGINX config** — look for header-based routing to a debug container.
4. **Read project docs** — check `Docs/XDEBUG_SETUP.md` or `docs/` for setup instructions.
5. **Check `.env`** — look for `DOCKER_XDEBUG_MODE` and `DOCKER_XDEBUG_PORT`.

## Dual-container architecture

Many projects use two PHP containers for optimal performance:

| Container | Purpose | When used |
|---|---|---|
| `*-php` | Fast PHP-FPM, no Xdebug overhead | All normal requests |
| `*-php-xdebug` | PHP-FPM with Xdebug enabled | Only debug requests |

NGINX routes requests based on HTTP headers:
- **No debug header** → fast container (no Xdebug)
- **Debug header present** → Xdebug container

### Debug headers

| Header | Value | Recommended for |
|---|---|---|
| `X-Xdebug-Enable` | `1` or `true` | Manual tests, Postman |
| `X-Debug-Session` | `PHPSTORM` | IDE integration |
| `XDEBUG-SESSION` | any value | Standard Xdebug header |

**Important:** Use hyphens, not underscores. `XDEBUG_SESSION` does NOT work — use `XDEBUG-SESSION`.

### Verify routing

Check the `X-PHP-Backend` response header to confirm which container handled the request:

```bash
# Normal request
curl -I http://localhost:8002/  # → X-PHP-Backend: *-php:9000

# Debug request
curl -I -H "X-Xdebug-Enable: 1" http://localhost:8002/  # → X-PHP-Backend: *-php-xdebug:9000
```

## Xdebug configuration

### Environment variables

```bash
DOCKER_XDEBUG_MODE=develop,debug,coverage   # Xdebug modes
DOCKER_XDEBUG_PORT=9003                      # IDE listens on this port
```

### Xdebug modes

| Mode | Purpose |
|---|---|
| `debug` | Step debugging with breakpoints |
| `develop` | Enhanced error messages, var_dump improvements |
| `coverage` | Code coverage for tests |
| `profile` | Performance profiling (generates cachegrind files) |
| `trace` | Function call tracing |

### PHP-FPM on-demand (Xdebug container)

The Xdebug container typically uses `pm = ondemand` to save resources:
- Workers start only when a debug request arrives
- Idle workers terminate after 60s
- Reduces memory usage by ~60-70% when not debugging
- Unlimited request timeout for breakpoint sessions

## IDE setup

### PhpStorm

1. **Debug port**: Settings → PHP → Debug → Port: `9003`
2. **Enable listening**: Click "Start Listening for PHP Debug Connections" (phone icon)
3. **Server config**: Settings → PHP → Servers:
   - Host: `localhost`, Port: `80` (internal container port, not host port)
   - Enable path mappings: local project root → `/var/www/html`
4. **Browser extension**: Install "Xdebug helper", set IDE key to `PHPSTORM`

### VS Code

```json
{
  "name": "Listen for Xdebug",
  "type": "php",
  "request": "launch",
  "port": 9003,
  "pathMappings": {
    "/var/www/html": "${workspaceFolder}"
  }
}
```

## Debugging workflow

1. **Start listening** in IDE (PhpStorm: green phone icon)
2. **Set breakpoints** in code
3. **Send request with debug header** (browser extension, Postman, or curl)
4. **IDE breaks** at breakpoint → inspect variables, step through code
5. **Check `X-PHP-Backend` header** if debugging doesn't trigger

## CLI debugging (Artisan commands, tests)

For debugging Artisan commands or tests, enter the Xdebug container:

```bash
make console-xdebug    # Enter Xdebug container
php artisan your:command   # Xdebug connects to IDE automatically
```

### Verifying CLI fixes

After a fix, verify the command without re-attaching the debugger:

```bash
# Run the command, capture exit code + command output
php artisan your:command; echo "exit code: $?"

# Pest CLI assertion — expectsOutput / artisan test
vendor/bin/pest --filter='ProcessInvoicesCommand'
```

Assert on the **exit code** and **command output**; never trust "looks fine" from breakpoint inspection alone.

## Troubleshooting

| Problem | Solution |
|---|---|
| Breakpoints not hit | Check IDE is listening, verify path mappings, check `X-PHP-Backend` header |
| IDE not connecting | `make console-xdebug` then `nc -zv host.docker.internal 9003` — should show "open" |
| Wrong container used | Check response header `X-PHP-Backend`, verify debug header format (hyphens!) |
| Slow normal requests | Verify normal requests go to fast container (no `X-PHP-Backend: *-xdebug*`) |
| Xdebug logs | `make console-xdebug` then `tail -f /tmp/xdebug.log` |
| Container not running | `docker compose ps` — both PHP containers should be "Up" |
| Path mapping wrong | PhpStorm: Settings → PHP → Servers → verify local ↔ `/var/www/html` |

## Container management

```bash
make console              # Fast PHP container (no Xdebug)
make console-xdebug       # Xdebug container
make rebuild-php-xdebug   # Rebuild Xdebug container only
make rebuild-php-all      # Rebuild both PHP containers
```

### Filter noisy debug output

`tail -f /tmp/xdebug.log` and `docker logs` produce far too much
data to read line-by-line. Filter with `rg`/`grep` for the relevant
event:

```bash
# Only connection / breakpoint events
rg --color=never 'Connect|Step|breakpoint' /tmp/xdebug.log

# Only this request's frames in the laravel log
docker compose logs php-xdebug | rg --color=never "$REQUEST_ID"
```

## What NOT to do

- Do not leave Xdebug enabled in production containers.
- Do not use underscores in debug headers (`XDEBUG_SESSION` fails — use `XDEBUG-SESSION`).
- Do not set PhpStorm server port to the host port (e.g. 8002) — use the internal port (80).
- Do not run performance benchmarks against the Xdebug container.
- Do not forget to check path mappings when breakpoints are silently skipped.


## Output format

1. Xdebug configuration or debugging session setup
2. Root cause identified with evidence from debugger output

## Gotcha

- Xdebug runs in a separate container — don't confuse the fast container (port 80) with the debug container (port 8080).
- The model tends to suggest `dd()` or `var_dump()` — they're forbidden by PHPStan config. Use Xdebug breakpoints.
- Step-debugging over HTTP requires the `XDEBUG_SESSION` cookie/header — without it, breakpoints don't trigger.

## Do NOT

- Do NOT leave breakpoints or debug code in committed files.
- Do NOT use var_dump() or dd() — use Xdebug breakpoints.
- Do NOT debug in the fast container — switch to the Xdebug container.

## Clarification guard — ambiguous repro → ask

If the bug repro is unclear (which request, which user, which env, which input shape?), do not start placing breakpoints at random. Ask the user for the failing payload, the exact route, or the Sentry trace. Setting breakpoints based on a guessed flow wastes a session.

## Auto-trigger keywords

- Xdebug
- PHP debugging
- breakpoint
- step debugging

## Known Laravel bug patterns (from bug-analyzer)

- N+1 queries hidden in loops or accessors
- Missing `->fresh()` after update when using same instance
- Eloquent lazy loading in queued jobs (serialization issues)
- `now()` timezone mismatches
- Missing FK constraints allowing orphaned records
- `DB::transaction()` with external side effects (emails, API calls)
- Model events firing during seeding or migration
- Off-by-one errors in pagination or date ranges
- Silent exception swallowing (`catch (\Exception $e) {}`)
- Floating point comparison for money/quantities

Versions

The database has no other skills named php-debugging.

Database snapshot: 13.11.2026 · package version ebd36c1d3bd1 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100phpstorm
    Expert PhpStorm assistance covering PHP language tooling, Laravel/Symfony integrations, Xdebug setup, Composer dependency inspection, and database tooling. Use when configuring Xdebug remote debugging, setting up PHPStan/Psalm inspections, optimizing IDE performance, or debugging PHP applications.
  • 92write-script-php
    MUST use when writing PHP scripts.
  • 100php
    PHP language conventions, modern idioms, and type system. Invoke whenever task involves any interaction with PHP code — writing, reviewing, refactoring, debugging, or understanding PHP projects.
  • 100upgrade-php
    PHP Upgrade Assistant. Use when upgrading PHP version, fixing deprecations for a target PHP version, or scanning for PHP compatibility issues.
  • 100programming-php
    PHP 8 practices: typed concise code, features through PHP 8.5, input validation, quality checks. Use when writing or reviewing PHP in Composer projects.
  • 100run-on-3v4l
    Execute PHP code on 3v4l.org to test runtime behavior across multiple PHP versions. Use when you need to verify what PHP actually does with a piece of code.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.