Update 2021 - Fully integrate DDEV and PHPStorm - including Unit Tests with Coverage

In a previous post I described using SSH to integrate DDEV and PHPStorm. As that seems a bit circular, I decided to try to directly integrate DDEV and PHPStorm via docker-compose.

Integrating via docker-compose has the advantage that path mappings for example are available automatically.

This is how to do it:

Dump docker-compose config

DDEV is using their own wrapper script to start docker-compose and does a few things in it that PHPStorm cannot directly understand - which is why we cannot use the docker-compose file of DDEV directly. However, DDEV has a debug command that is able to dump the "final" docker-compose config, which we can use to dump that in a PHPStorm compatible format:

ddev debug compose-config > build/docker-compose.yml

Adjust docker-compose.yml

This section is mainly necessary because of a bug in PHPStorm (tracked here: https://youtrack.jetbrains.com/issue/IDEA-262108), as it's already fixed in master, we can expect to get rid of this workaround soon. 

In the compose config we just dumped is a port configuration which PHPStorm (2021.1) cannot parse. As we don't need that port configuration, we can get away with simply removing the offending lines. In the file build/docker-compose.yml look for the "ports" part in the "web" container section and remove it.

Delete the following lines:


Windows users should additionally check whether the first line contains logging output - if so: please delete that, too.

Here's a host command you can use in DDEV to automate the creation of the file (Thanks to Chris Wolff):

## Description: erxport a docker-compose.yml for use with php storm.
## Usage: phpstormcompose [compose-yaml file/path]
## Example: "ddev phpstormcompose build/docker-compose.yml"
set -eu
ddev debug compose-config | \
  # Remove windows Debug output
  sed 's/Running  Command=.*//g' | \
  # Remove localhost bindings
  sed -r 's#\s- 127\.0\.0\.1\:\:(80|443)/tcp##g' | \
  # convert newlines to formfeed (so we can do multiline replacment
  tr '\n' '\f' | \
  # convert empty port: into empty array port: []
  sed -r 's/ports:\f\s+\f\s+\f/ports: \[\]\f/g' | \
  # convert formfeed back to newline
  tr '\f' '\n' > \
echo "created: ${COMPOSE_FILE}"

Add PHPStorm Docker-Compose PHP Interpreter

  • In PHPStorm, go to "File" > "Settings" > "PHP" and add a new "CLI Interpreter" from "Remote ... Docker Compose".
  • Choose "Docker Compose"
  • Choose the configuration file (build/docker-compose.yml) we just dumped and adjusted
  • Set the environment variable "COMPOSE_PROJECT_NAME=ddev-<your-ddev-project-name>"
  • Click OK.
  • In the "CLI Interpreters" view in the section "Lifecycle" choose "Connect to existing container"
  • Save and close.

Set Remote Interpreter for Composer and Testing

In the PHPStorm Settings, go to "PHP"  > "Composer" and choose "Remote Interpreter" --> the one we just configured.

At "PHP" > "Test Frameworks" click the plus (add) and choose "PHPUnit by Remote Interpreter". Choose our new CLI Interpreter and load PHPUnit via composer from "/var/www/html/vendor/autoload.php".

Run Tests in PHPStorm with DDEV

Running the tests in PHPStorm now works exactly in the same way as it does without DDEV, for example: click on a phpunit.xml file and choose "Run" from the context menu. This will create a new "Run Configuration". If you need to make additional adjustments, go to the "Run Configuration" settings.

Debug tests in PHPStorm with DDEV

To debug tests in PHPStorm with DDEV, first enable xdebug in DDEV:

ddev xdebug on

Then choose a test and right-click -> Debug (or use the debug button). PHPStorm will now stop at any breakpoint and allow you to step through the tests.

Run tests with coverage in PHPStorm with DDEV

Make sure you have set the coverage engine to "Xdebug" in the PHPStorm "Run Configuration" for your tests (see screenshot above).

Then enable xdebug in DDEV (see above).

You can now click on "Run tests with Coverage" to generate code coverage that PHPStorm will display inline. Thanks to the path mappings contained in the docker-compose file you should not have any problems with matching coverage and files.

Feedback welcome
That's it for now, if you have any feedback, don't hesitate to contact me via Twitter (@sasunegomo) or TYPO3 Slack (@susi).