Skip to content

Local setup

The recommended development setup uses DDEV with the dns module symlinked into a Drupal sandbox via a Composer path repository. This is the same pattern used for sister contrib modules in the same workflow (e.g. field_ipaddress).

Layout

Side-by-side directories on the host:

~/src/
├── sandbox/         # any DDEV-driven Drupal site you want to test against
└── dns/             # this module's checkout

Substitute your own paths and project names below; the directory structure is what matters, not the names.

Wire dns into the sandbox

In the sandbox repo, add a DDEV docker-compose addon that mounts the module's host directory into the container:

# .ddev/docker-compose.dns.yaml
services:
  web:
    volumes:
      - ../../dns:/var/www/dns

Then add a Composer path repository pointing at the in-container mount path, and require the module from it:

// composer.json
{
  "repositories": [
    {
      "type": "path",
      "url": "/var/www/dns",
      "options": {
        "symlink": true
      }
    }
    // …other repos…
  ],
  "require": {
    "drupal/dns": "@dev"
    // …
  },
  "config": {
    "preferred-install": {
      "drupal/dns": "source"
    }
  }
}

Bring it up:

ddev restart                          # picks up the new mount
ddev composer require drupal/dns:@dev # symlinks
ddev drush en dns -y

Verifying class autoload

If you add a new class and Drupal can't find it, the diagnostic that nails 90% of cases:

ddev drush php:eval '
$fqn = "Drupal\\dns\\YourNewClass";
$loader = require DRUPAL_ROOT . "/autoload.php";
echo "exists: " . (class_exists($fqn) ? "YES" : "NO") . "\n";
echo "file: "   . var_export($loader->findFile($fqn), true) . "\n";
echo "psr4: "   . var_export($loader->getPrefixesPsr4()["Drupal\\dns\\"] ?? "NOT REGISTERED", true) . "\n";
'

If this returns YES from CLI but the web request still says "Class does not exist," it's almost always the Drupal compiled-container cache (especially under Redis). Flush it:

ddev redis-cli FLUSHALL
ddev drush cr

Cache discipline

Most of the iteration headaches in development come from stale caches. Standard reset that catches everything:

ddev redis-cli FLUSHALL
ddev drush cr

This is what drush cr should do on its own, but Redis-backed bootstrap container caches aren't always cleared by it. The combination is reliable.

Testing the documentation site locally

The simplest path uses the Metadrop/ddev-mkdocs addon to run the mkdocs server inside DDEV — no Python toolchain on the host. From the dns module's checkout:

ddev get Metadrop/ddev-mkdocs
ddev restart
ddev mkdocs serve

DDEV prints the URL on startup (typically a *.ddev.site host). Live-reloads on save. The addon isn't actively maintained but works reliably for local previewing of the mkdocs site.

If you'd rather run mkdocs on the host directly:

pip install mkdocs-material
mkdocs serve

Opens at http://localhost:8000/.