PHP Runtime And Server Environment

DDEV For Local PHP Development

DDEV provides a project-oriented local development environment on top of containers. It can configure a web container, PHP, a database, local HTTPS, captured mail, and common developer tools behind one command-line interface.

It is useful when a team wants a repeatable environment without maintaining every Compose detail itself. You should still understand document roots, PHP versions, extensions, services, volumes, and environment variables because DDEV configures those concerns rather than making them disappear.

Prerequisites

Install a container provider supported by DDEV, then install DDEV itself. Confirm both are working before configuring a project:

ddev version
ddev list

The exact host installation steps differ across Linux, macOS, Windows, WSL, and container providers. Follow the current DDEV installation documentation for the host instead of copying an old package command from a project README.

Configure An Existing Project

From the project root, run the interactive configurator:

ddev config

For a conventional PHP application whose public document root is public/, an explicit starting command can be:

ddev config --project-type=php --docroot=public

Review the detected values. The document root must point at the web-accessible directory, not automatically at the repository root. Select the PHP and database versions required by the project rather than accepting defaults without checking.

DDEV writes project configuration under .ddev/, including .ddev/config.yaml. Commit the shared project configuration and its generated ignore rules. Do not commit developer secrets, database exports, or machine-specific credentials merely because they are near that directory.

Start And Inspect The Environment

ddev start
ddev describe
ddev launch

ddev start creates or starts the project services. ddev describe reports URLs and service details. ddev launch opens the project URL when a browser is available.

Inspect the runtime that actually serves the application:

ddev php --version
ddev exec php -m
ddev exec php --ini
ddev logs

A correct host PHP installation does not compensate for a wrong PHP version or missing extension in the DDEV web container.

Run Project Tools Inside DDEV

DDEV includes commands for common tools:

ddev composer install
ddev exec vendor/bin/phpunit
ddev exec vendor/bin/phpstan analyse
ddev npm install
ddev ssh

ddev exec runs a command in the web container by default. ddev ssh opens an interactive shell. Framework-aware projects may also expose commands such as ddev artisan or ddev console.

Choose one documented way to run each project command. Mixing host Composer, container PHP, and host-generated files can produce inconsistent dependency checks and file ownership.

Database Workflows

A new developer may need a sanitized development database:

ddev import-db --file=backups/development.sql.gz
ddev export-db --file=/tmp/development.sql.gz

Treat imports as data-changing operations. Confirm the active project and source file before running them. Production data should be minimized, sanitized, access-controlled, and handled according to the project's data policy.

Snapshots can provide quick local restore points, but they are not a replacement for a tested backup and migration strategy.

Xdebug

Enable step debugging only while it is needed:

ddev xdebug on
ddev xdebug status
ddev xdebug off

Leaving Xdebug enabled can slow requests and command-line work. The editor must listen for the configured connection and use correct container-to-workspace path mappings.

Stop, Power Off, And Delete

These commands have different scopes:

ddev stop
ddev poweroff
ddev delete

ddev stop removes a project's containers without normally discarding its database. ddev poweroff stops all DDEV projects and resources. ddev delete removes DDEV's project information and active database while leaving the source code and .ddev/ directory alone.

By default, current DDEV releases create a database snapshot before ddev delete. The --omit-snapshot option skips that protection, and a global setting can change the default. Treat the snapshot as a recovery aid, not as the project's only backup.

Options such as ddev stop --remove-data are destructive to local project data. Read command help and preserve anything needed before using them:

ddev help stop
ddev help delete

Extend Deliberately

DDEV add-ons and custom Compose files can add services such as search engines or queues. They also add versions, configuration, startup cost, and maintenance.

Add a service because the application depends on it, pin or constrain versions where appropriate, and document initialization and health checks. Prefer committed automation over setup steps that exist only in one developer's shell history.

Team Workflow

Constrain And Inspect The Shared Environment

A team can record a compatible DDEV range with ddev_version_constraint in .ddev/config.yaml. This catches unsupported host installations before developers debug differences caused by materially different DDEV releases. Update the constraint deliberately when the project adopts a new feature or drops an old host version.

Inspect the merged project configuration when generated files, overrides, or global settings make behaviour unclear:

ddev utility configyaml
ddev utility configyaml --full-yaml --omit-keys=web_environment

The second command is useful for detailed review while omitting environment values that may be sensitive. Effective configuration can differ from the visible base file because DDEV combines project config, override files, add-ons, and global settings.

When startup, DNS, HTTPS, or container-provider behaviour differs between machines, collect evidence before changing project config:

ddev utility diagnose
ddev logs

ddev utility diagnose checks the container provider, networking, DNS, local HTTPS setup, and current project health. If support needs comprehensive diagnostics, use the command recommended by the current DDEV troubleshooting documentation and review output for credentials before sharing it.

Use Named Snapshots For Local Recovery

Before a risky local schema experiment or database replacement, a named snapshot can provide a quick restore point:

ddev snapshot --name=before-order-migration
ddev snapshot --list
ddev snapshot restore before-order-migration

Snapshots live in DDEV-managed project storage and are tied to compatible database tooling. They are convenient for local recovery, but they should not be treated as portable production backups or committed fixtures.

ddev import-db replaces the active local database content. If existing local work matters, export it or take a snapshot before importing. Confirm the project name with ddev describe; commands run from the wrong repository can alter the wrong local database just as effectively as commands run against the intended one.

A useful onboarding path is:

  1. clone the repository
  2. install the documented DDEV and container-provider versions
  3. run ddev start
  4. install dependencies inside DDEV
  5. import approved development data or run migrations and seeders
  6. run the project's verification commands
  7. confirm the application URL and captured-mail workflow

Keep .ddev/ changes in normal code review. A PHP-version, database-version, extension, or service change affects every developer and should not arrive as an unexplained local tweak.

What DDEV Does Not Guarantee

DDEV does not automatically guarantee production parity. Production may use different images, web servers, orchestration, storage, scaling, or security controls.

Use DDEV to make local development consistent. Separately test deployment artifacts and production-relevant behavior in CI or staging.

What To Remember

DDEV turns common container operations into project commands and committed configuration. Verify the detected document root and versions, run project tools in the actual environment, protect data, disable debugging when finished, and understand which lifecycle commands discard state.

Before moving on, make sure you can explain what belongs in .ddev/, when to use ddev exec, and why ddev stop and ddev delete are not interchangeable.

Practice

Task: Plan A DDEV Onboarding Workflow
  • composer.json in the repository root;
  • public/index.php as its web entry point;
  • a database migration command at php bin/console doctrine:migrations:migrate;
  • PHPUnit at vendor/bin/phpunit;
  • an approved sanitized database export at backups/development.sql.gz;
  • a shared DDEV version constraint in .ddev/config.yaml.

Write an ordered onboarding workflow that:

  1. verifies the installed DDEV and container-provider details;
  2. configures the correct document root without discarding reviewed settings;
  3. starts and describes the intended project;
  4. checks the container PHP version and extensions;
  5. installs Composer dependencies inside DDEV;
  6. protects any existing local database before import;
  7. imports the approved database, then runs migrations and tests;
  8. enables Xdebug for one debugging session and disables it afterward;
  9. collects useful diagnostics if startup or HTTPS fails;
  10. stops the project without deleting its database.

Identify which .ddev/ configuration should be reviewed and committed, how to inspect merged configuration without exposing environment values, and which commands or options require explicit data-loss warnings.

Show solution
ddev version
ddev utility configyaml --full-yaml --omit-keys=web_environment
ddev config --project-type=php --docroot=public
ddev start
ddev describe
ddev php --version
ddev exec php -m
ddev composer install

ddev config preserves existing settings unless explicit flags change them. Confirm the installed DDEV satisfies the committed constraint and that ddev describe names the intended project before any database operation.

If the project already contains local data worth retaining, take a named snapshot first:

ddev snapshot --name=before-onboarding-import
ddev snapshot --list

A completely new empty project does not gain useful protection from that snapshot. Import the approved sanitized data, then bring its schema forward and verify the application:

ddev import-db --file=backups/development.sql.gz
ddev exec php bin/console doctrine:migrations:migrate
ddev exec vendor/bin/phpunit

The import replaces current local database content. Confirm the source file, active project, and recovery need before running it.

For one debugging session:

ddev xdebug on
ddev xdebug status
ddev xdebug off

Reproduce the request while the editor is listening and has correct container path mappings. If startup, DNS, or HTTPS fails, collect evidence before editing configuration:

ddev utility diagnose
ddev logs

For a snapshot recovery, use ddev snapshot restore before-onboarding-import. Restoring also changes local database state, so verify the snapshot and project first.

Review and commit shared .ddev/config.yaml, generated ignore rules, reviewed add-on configuration, and intentional Compose overrides. Do not commit database exports, credentials, or developer-specific secret overrides. The processed-config command omits web_environment so the review does not print those values.

Finish with:

ddev stop

ddev stop preserves stored project data. ddev import-db, snapshot restore, ddev delete, and especially ddev stop --remove-data require clear data-change or data-loss warnings. A DDEV snapshot is a local recovery aid, not the project's only backup.