This repository demonstrates how to develop a Craft CMS plugin with Craft installed in a subdirectory while using DDEV as the local runtime.
-
Plugin lives in
src/: The plugin code is insrcwith PSR-4 autoloading (viget\\ddev\\→src/). This matches typical Craft plugin scaffolds. -
Craft installed in
craft-install/: Instead of installing Craft at the repository root, Craft is installed in thecraft-installsubdirectory. DDEV is configured withdocroot: craft-install/webso web requests are served fromcraft-install/web. -
Composer path repository from Craft to repo root: In
craft-install/composer.json, there is a repository entry:"repositories": [ { "type": "composer", "url": "https://composer.craftcms.com", "canonical": false }, { "type": "path", "url": "../" } ]
- What this does: The
type: pathrepository tells Composer (running insidecraft-install/) to treat the directory one level up (../) as a Composer package source. That allows the Craft project to require and load the plugin that lives at the repository root without publishing it to Packagist. Composer installs it via a symlink, so edits insrc/are immediately reflected in Craft.
- What this does: The
-
Root-level
craftCLI: Acraftexecutable at the repo root bootstraps viacraft-install/bootstrap.phpand runs Craft's console application. This meansddev craft <command>works as expected since DDEV'scraftcmsproject type automatically detects and uses it.
-
Root plugin package and handle:
{ "name": "viget/ddev-plugin", "type": "craft-plugin", "autoload": { "psr-4": { "viget\\\\ddev\\\\": "src/" } }, "extra": { "handle": "ddev-plugin" } } -
DDEV config (docroot and PHP):
name: ddev-craft-plugin type: craftcms docroot: craft-install/web composer_root: "." php_version: "8.3" webserver_type: nginx-fpm
ddev start # Start the environment
ddev craft help # Run Craft CLI commands
ddev craft migrate/all # Run migrations
ddev composer install # Installs plugin dependencies (runs at repo root)
ddev composer install --dir craft-install # Installs Craft app dependenciescomposer_rootis set to.in.ddev/config.yaml, soddev composeroperates on the plugin's rootcomposer.jsonby default. Useddev composer install --dir craft-installwhen you need to update the Craft app's dependencies.- Because the plugin is installed via a path repository, Composer links it as a symlink. Changes in
src/are available immediately without reinstalling.