understand them instead of trial and error
Breakpoints that never hit, Xdebug connecting but failing to find the files, deployments that land in the wrong path: almost all of these problems share the same cause, misconfigured or missing Path Mappings. Once you understand the concept, you solve these problems in minutes.
Table of Contents
- 1. What Path Mappings really are
- 2. Configuring Path Mappings for Xdebug
- 3. Docker containers: mapping local and container paths correctly
- 4. Deployment servers and upload paths
- 5. Remote PHP interpreters and their path configuration
- 6. Diagnosis: why isn't my breakpoint hitting?
- 7. Symlinks and nested projects
- 8. Path Mappings in Magento 2 projects with Docker
- 9. Configuration scenarios compared
- 10. Summary
- 11. FAQ
1. What Path Mappings really are
A Path Mapping is a translation rule between two file systems. On one side sits the developer's local file system: the path under which PhpStorm knows the source files. On the other side sits the remote file system: the path under which PHP, whether inside a Docker container, on a staging server, or in a remote interpreter, sees the same file. Without this translation, PhpStorm cannot map a hint pointing to /var/www/html/vendor/magento/module-catalog/Model/Product.php from the Xdebug server back to the local file at /home/mir/development/mironsoft/src/vendor/magento/module-catalog/Model/Product.php.
Path Mappings aren't a feature you configure once and forget. Every time the project structure changes, a new Docker volume gets mounted, or a new server is added, the mappings need to be updated. The misconception behind most debugging problems is the assumption that PhpStorm can derive the paths automatically. The IDE can only do that in very simple cases; with Docker containers, remote servers and nested project structures, you have to specify them explicitly.
2. Configuring Path Mappings for Xdebug
Xdebug connects to PhpStorm and tells the IDE which file it's currently working on, using the path as PHP sees it, not as PhpStorm sees it. PhpStorm has to translate this path to open the correct local file. Configuration happens under Settings → PHP → Debug → DBGp Proxy for the connection parameters and under Settings → PHP → Servers for the Path Mappings themselves. Important: every server entry in PhpStorm has a name, and that name must match exactly the value of the Xdebug environment variable PHP_IDE_CONFIG=serverName=SERVERNAME.
The most common source of errors: you create a server entry named "localhost", but set PHP_IDE_CONFIG=serverName=docker in the Docker Compose file. PhpStorm can't match the incoming Xdebug connection to any server entry and either automatically creates a new entry without mappings or discards the connection. The result: breakpoints never hit, even though the debugger connects. The fix is trivial once you understand the concept: the server name in PhpStorm has to equal the serverName value in PHP_IDE_CONFIG.
# docker-compose.yml - Xdebug configuration with correct serverName
services:
phpfpm:
image: markoshust/magento-php:8.4-fpm
environment:
# CRITICAL: serverName must match PhpStorm → Settings → PHP → Servers → Name
PHP_IDE_CONFIG: "serverName=mironsoft-docker"
XDEBUG_MODE: "debug"
XDEBUG_CONFIG: >-
client_host=host-gateway
client_port=9003
start_with_request=trigger
idekey=PHPSTORM
volumes:
- ./src:/var/www/html:delegated
# PhpStorm → Settings → PHP → Servers:
# Name: mironsoft-docker ← must match PHP_IDE_CONFIG serverName
# Host: localhost
# Port: 80
# Debugger: Xdebug
# Path Mappings:
# /home/mir/development/mironsoft/src → /var/www/html
3. Docker containers: mapping local and container paths correctly
In Docker-based projects, the volume mapping is the central starting point for Path Mappings. If ./src:/var/www/html is defined in docker-compose.yml, then the Path Mapping in PhpStorm is just as simple: local path /home/mir/development/mironsoft/src maps to container path /var/www/html. This one mapping is enough for every file below that directory, PhpStorm resolves subdirectories relative to it automatically.
Things get more complicated when multiple volumes are mounted or when Composer packages live outside the main directory. In Magento projects, where local modules from app/code and vendor packages from vendor all run inside the same container, a single root mapping is enough. It gets critical when symlinks are involved, or when the same code is reachable via two different paths inside the container. In those cases you need to add additional, more specific mappings, which PhpStorm applies with higher priority than the more general root mapping.
4. Deployment servers and upload paths
PhpStorm deployment configurations under Settings → Build, Execution, Deployment → Deployment also use Path Mappings. Here you get three paths: the Local path (on the developer's machine), the Deployment path (on the remote server) and, optionally, a Web path (for browser URL mapping). Together these three fields make up the deployment mapping.
A common mistake is entering the project's root path correctly but getting the deployment path relative to the server's web root wrong. If the server hosts Magento under /var/www/vhosts/mironsoft.de/httpdocs, but you enter /var/www/html, uploads end up in the wrong place without any error message. PhpStorm transfers the files successfully, just to a location nobody expects. Testing the deployment configuration with Tools → Deployment → Browse Remote Host immediately shows whether PhpStorm is reaching the right path.
# PhpStorm deployment configuration - Settings → Build, Execution, Deployment → Deployment
# Type: SFTP
# Connection:
# Host: staging.mironsoft.de
# Port: 22
# User: deploy
# Auth: Key pair ~/.ssh/id_ed25519
# Mappings (tab "Mappings"):
# Local Path: /home/mir/development/mironsoft/src
# Deployment Path: /var/www/vhosts/mironsoft.de/httpdocs
# Web Path: /
# Excluded Paths (tab "Excluded Paths") - never upload:
# /home/mir/development/mironsoft/src/var
# /home/mir/development/mironsoft/src/pub/static
# /home/mir/development/mironsoft/src/.git
# /home/mir/development/mironsoft/src/vendor
# Automatic upload:
# Tools → Deployment → Options → Upload changed files automatically: Always
# (use only for staging, never for production)
5. Remote PHP interpreters and their path configuration
When PhpStorm uses a remote PHP interpreter, meaning PHP inside a Docker container or on a remote server instead of local PHP, the IDE needs to know how the paths between the systems relate to each other. The remote interpreter is configured under Settings → PHP → CLI Interpreter. For Docker-based interpreters, you select the container and specify the path to the PHP binary inside it.
For Docker interpreters, PhpStorm automatically tries to read the volume mappings from docker-compose.yml and derive Path Mappings from them. That works well in simple cases but fails with complex Compose setups involving multiple services or override files. In those cases, you need to enter the mappings manually in the interpreter configuration. The advantage of manual mappings: they are explicit, traceable, and don't silently break when the Compose file changes.
6. Diagnosis: why isn't my breakpoint hitting?
When breakpoints in PhpStorm don't hit even though Xdebug is connected, the most common causes, in descending order of frequency, are: wrong server name in PHP_IDE_CONFIG, missing or incorrect Path Mapping, a breakpoint set in a cached file instead of the source file, or Xdebug running in the wrong mode (xdebug.mode must include debug). PhpStorm shows the paths received from the Xdebug server in the debug window under Debugger log, and that is the single most important piece of diagnostic information.
You enable the debugger log under Help → Diagnostic Tools → Debug Log Settings, then add #com.jetbrains.php.debug. After the next Xdebug request, the log file shows the exact paths Xdebug is reporting to PhpStorm. Comparing these against the configured Path Mappings immediately reveals whether a mapping is missing or wrong. A typical entry: received file path from debugger: /var/www/html/app/code/Mironsoft/Blog/Controller/Index.php, and the local mapping must contain exactly /var/www/html → /home/mir/development/mironsoft/src.
7. Symlinks and nested projects
Symlinks are a common cause of breakpoints that don't hit even though the mappings look correct at first glance. By default, PHP resolves symlinks and reports the real path to Xdebug, not the symbolic one. If a file lives under /var/www/html/app/code/Mironsoft/Blog but is linked in via a symlink from /home/user/modules/blog, Xdebug reports the real path /home/user/modules/blog/Controller/Index.php, and the mapping to /var/www/html simply doesn't apply.
The fix: either add the real path of the symlink target as an additional Path Mapping, or set xdebug.use_compression=0 in the PHP configuration and realpath_cache_size=0 in php.ini so PHP stops resolving symlinks (not recommended in production). In Magento projects using the Mark Shust Docker setup, no symlinks are needed at all, direct volume mounts avoid the problem entirely.
# xdebug.ini - complete Xdebug 3 configuration for Docker Magento projects
[xdebug]
xdebug.mode = debug,develop
xdebug.start_with_request = trigger
xdebug.client_host = host-gateway
xdebug.client_port = 9003
xdebug.idekey = PHPSTORM
xdebug.max_nesting_level = 512
xdebug.log_level = 0
; Path resolution: do NOT resolve symlinks (caution: performance impact)
; xdebug.resolve_symlinks = 0
; For CLI debugging (bin/magento commands):
; php -d xdebug.mode=debug -d xdebug.start_with_request=yes bin/magento ...
# PHP_IDE_CONFIG in docker-compose.yml:
# PHP_IDE_CONFIG: "serverName=mironsoft-docker"
# → Must match exactly the server name in PhpStorm → Settings → PHP → Servers
8. Path Mappings in Magento 2 projects with Docker
In the Mark Shust Docker setup for Magento 2, the Magento root inside the container sits at /var/www/html. Locally it lives under the project's src/ directory. The Path Mapping is therefore unambiguous: /home/mir/development/mironsoft/src → /var/www/html. This single mapping covers every file, Magento core files in vendor/magento, your own modules in app/code, theme files in app/design, and even the generated classes in generated.
To debug CLI commands like bin/magento cache:flush or your own console commands, you need a separate run/debug configuration in PhpStorm. A PHP Remote Debug configuration with the same server name isn't enough; for CLI commands you need to set xdebug.start_with_request=yes (instead of trigger) and start the command alongside the debug session. The Path Mappings are the same as for web requests, since the CLI PHP process runs in the same container with the same volume mounts.
9. Configuration scenarios compared
Depending on the development environment, different configuration requirements arise. The table below gives an overview of the three most common scenarios and their typical pitfalls.
| Scenario | Local path | Remote path | Typical mistake |
|---|---|---|---|
| Docker (Mark Shust) | …/mironsoft/src |
/var/www/html |
Wrong serverName |
| Staging server (SSH) | …/mironsoft/src |
/var/www/vhosts/… |
Wrong deployment path |
| Local PHP | …/mironsoft/src |
No mapping needed | Server entry still required |
| WSL2 (Windows) | \\wsl$\…\src |
/home/…/src |
Path separator conflict |
| Multiple containers | One local root | Different paths | Own server per container |
An important principle: PhpStorm needs a separate server entry with its own name for every Xdebug endpoint. If you debug PHP across multiple containers, say an FPM container for web requests and a CLI container for cron jobs, you need to create two server entries, even if the Path Mappings are identical. PHP_IDE_CONFIG then contains the name of the respective server entry.
Mironsoft
Docker development environments and PhpStorm setup for Magento teams
Finally got Xdebug and Docker debugging set up right?
We configure your complete development environment, from Docker Compose through Xdebug Path Mappings to a fully integrated PhpStorm setup for your Magento 2 team.
Docker setup
Set up the Mark Shust setup with correct Xdebug configuration and Path Mappings
PhpStorm configuration
Standardize server entries, interpreters and deployment mappings across the whole team
Onboarding
A reproducible development environment that gets new developers set up in minutes instead of hours
10. Summary
Path Mappings in PhpStorm are the bridge between two file systems. Once you understand that Xdebug, deployment and remote interpreters all use the same mechanism, configuration becomes logical and predictable. The server name in PhpStorm must match the serverName value in PHP_IDE_CONFIG. The Path Mapping translates the local path into the container or server path. One mapping per root directory is enough for every file underneath it.
The fastest way to diagnose breakpoints that won't hit: enable the debugger log, read the path Xdebug is reporting, compare it against the configured mappings. In 90% of cases the cause is either a wrong server name or a forgotten mapping. With this understanding, you solve Path Mapping problems in two minutes instead of two hours.
Path Mappings in PhpStorm: the essentials at a glance
Server name
PhpStorm → Settings → PHP → Servers → Name must match exactly the value of PHP_IDE_CONFIG=serverName=NAME. Wrong spelling means breakpoints never hit.
Docker mapping
Local path to src/ → container path /var/www/html. One root mapping is enough for every file underneath it. Matches the volume entry in docker-compose.yml.
Diagnosis
Help → Diagnostic Tools → Debug Log Settings → #com.jetbrains.php.debug. The log shows exact paths from the Xdebug server, comparing them with the mapping reveals the error instantly.
Symlinks
PHP resolves symlinks to real paths. Xdebug reports real paths. Add the symlink targets as an additional mapping, or replace symlinks with direct volume mounts.
11. FAQ: Path Mappings in PhpStorm
1Why don't breakpoints hit despite an Xdebug connection?
serverName value in PHP_IDE_CONFIG. Second cause: missing or incorrect Path Mapping.2What is PHP_IDE_CONFIG?
serverName=NAME. Tells Xdebug which PhpStorm server entry the connection should be matched to. Set incorrectly, you get a connection but no breakpoints.3How many Path Mappings do I need for Docker Magento?
…/src → /var/www/html. PhpStorm resolves subdirectories relative to it. More only with symlinks or several separate volumes.4How do I enable the Xdebug log?
#com.jetbrains.php.debug. The log shows exact paths from the Xdebug server. Comparing them with the mappings reveals the error instantly.5Can Xdebug and deployment mapping be shared?
6Does PhpStorm detect Docker volumes automatically?
7What do I do about symlinks preventing breakpoints?
8How do I debug bin/magento commands in Docker?
xdebug.start_with_request=yes and run the command in the container while PhpStorm is waiting for a connection. Path Mappings are identical to web request debugging.9How do I test whether deployment paths are correct?
10Do I need a separate server entry per container?
PHP_IDE_CONFIG value.