Skip to content

feat: declare the schema and cache commands, and wire Drupal through the file it reads - #36

Merged
geodro merged 6 commits into
mainfrom
feat/declare-migrate-command-and-drupal-settings
Aug 8, 2026
Merged

feat: declare the schema and cache commands, and wire Drupal through the file it reads#36
geodro merged 6 commits into
mainfrom
feat/declare-migrate-command-and-drupal-settings

Conversation

@geodro

@geodro geodro commented Aug 8, 2026

Copy link
Copy Markdown
Member

Four things the engine now asks a definition to say, each of which it could not say before. Twenty nine definitions across nine frameworks change.

Every definition that has a command applying the schema names it, through the migrate_command the doctor reads. It was matched against the literal word "migrate" before, which is Laravel's spelling, so a Symfony site was told its database was empty and to run migrations with no way to run them, and Drupal the same. Laravel, CakePHP, CodeIgniter and Tempest name migrate, Symfony names doctrine:migrations:migrate, Drupal names updb. A framework naming a command it does not have gets no button rather than one that maps to nothing.

Drupal's env block moves to the settings.php it actually reads. Its database lives in a $databases array its own installer writes there, and the previous declaration wrote DB_DRIVER and DB_HOST as PHP constants into that same file, which Drupal never looks at, while the .env the install command sourced was never created at all. A project picking mysql went on running whatever settings.php already said, with lerd reporting the site wired and its databases created. The block addresses the array directly through the php-vars format, so lerd writes the driver, host, port, database and credentials, plus the namespace and autoload path on the versions that ship the module based drivers. Versions 8 and 9 predate those drivers and spell the namespace differently, so they set only the connection coordinates and leave whatever the installer wrote in place, which is correct for either spelling but is the part of this I could not verify against a running site.

The declaration stays readable by a binary that predates php-vars: file and format still name the .env and dotenv an older lerd knows how to write, and app_file and app_format are the additive pair a current one prefers. Checked against a v1.32.0 build, which leaves settings.php byte for byte rather than writing into it, where today's published definition injects a define() it never reads.

Drupal, WordPress and Magento decline the repeated query warning. Their entity, config and cache layers issue the repeats during an ordinary request, so the warning names a loop inside the framework that nobody using it can change, and browsing an admin fires one after another. Every framework whose queries come from the code a developer writes keeps it, which is Laravel, Symfony, CakePHP, CodeIgniter, Statamic and Tempest.

Every framework with a console names the subcommand that drops its compiled caches, so lerd can run it after rewriting a project's connection. Drupal names cr, Laravel and Statamic optimize:clear, Symfony cache:clear, Magento cache:flush, CakePHP cache clear_all, CodeIgniter cache:clear. A container built against the old database survives a swap and answers every request with an error about an entity type it can no longer find, which is a site that looks broken immediately after a move that worked.

Drupal also raises its CLI memory limit to 512M, because that rebuild is the thing that needs it: drush cr exhausts the 128M default part way through and leaves the site in exactly the state the rebuild was meant to clear.

The redis and mailpit blocks are dropped from Drupal. Neither ever reached the application: both wrote flat constants Drupal does not read. Mail from PHP now goes to the catcher through the sendmail path lerd configures for every container, whatever the framework. Redis is a real loss of intent and worth its own follow up: the contrib module reads a settings key with a dot inside the key itself, which a dotted path cannot address yet.

Driven end to end against a real Drupal 11 site: lerd env writes the connection into settings.php leaving the docblock and the other settings untouched, the doctor reports every service the project picks as wired, drush cr completes at the declared limit, and the site serves 200.

… reads

Two changes the engine now expects.

Every definition that has a command applying the schema names it, so the doctor can offer it as the fix for an empty or missing database. It was matched against the literal word "migrate" before, which is Laravel's spelling, so Symfony and Drupal were told to run migrations and given no way to run them. Laravel, CakePHP, CodeIgniter and Tempest name migrate, Symfony names doctrine:migrations:migrate, Drupal names updb.

Drupal's env block moves to the settings.php it actually reads. Its database lives in a $databases array its own installer writes there, and the previous declaration wrote DB_DRIVER and DB_HOST as PHP constants into the same file, which Drupal never looks at, while the .env the install command sourced was never created. A project picking mysql went on running whatever settings.php already said. The block addresses the array directly through the php-vars format, so lerd writes the driver, host, port, database, credentials and, on the versions that ship the module based drivers, the namespace and autoload path.

Versions 8 and 9 predate those drivers and spell the namespace differently, so they set only the connection coordinates and leave whatever the installer wrote in place.

The redis and mailpit blocks are dropped from Drupal. Neither ever reached the application: both wrote flat constants Drupal does not read, and mail from PHP now goes to the catcher through the sendmail path lerd configures, whatever the framework. Redis needs the contrib module's own settings key, which contains a dot inside the key itself and cannot be addressed by a dotted path yet.

The install command no longer sources a .env to build a database URL, since settings.php already holds the connection lerd wrote.
@geodro
geodro requested a review from a team as a code owner August 8, 2026 06:57
geodro added 4 commits August 8, 2026 10:10
The env block named settings.php with the php-vars format directly, which a binary released before that format cannot honour: its write path treats an unknown format as dotenv and appends key=value lines into the file, and a Drupal settings file so treated stops parsing. The store reaches every install within a day whatever version it runs, so that would have taken sites down on machines that had done nothing.

The block carries both answers now. file and fallback_file describe what an older binary should do, which is what it does today, writing constants into settings.php that Drupal ignores. app_file and app_format name the file the application actually reads, and a binary that knows those fields writes the $databases array Drupal runs on. An unknown field is ignored on parse, so one definition serves both.
The database step now offers SQLite only where a definition declares a sqlite service, so that a framework which cannot use one is not offered it. Laravel and Symfony both can, and declaring it is what keeps the option where it belongs: without this a Laravel project whose .env already says sqlite is walked through the wizard and comes out configured for mysql.

Laravel reads the flat pair it always has. Symfony reads the connection string its own recipe ships commented out, with the project directory placeholder it expects.
… drush

Drupal, WordPress and Magento issue their repeated queries from their own entity, config and cache layers during an ordinary request, so the warning names a loop inside the framework that nobody using it can change, and browsing an admin fires one after another. They decline it; the frameworks whose queries come from the code a developer writes keep it.

Drupal also gets a larger CLI memory limit. drush cr exhausts the 128M default on a Drupal CMS site, mid-rebuild, which is the state that leaves a site serving errors after its database moves.
Every framework with a console names the subcommand that drops its compiled caches, so lerd can run it after rewriting a project's connection. A container built against the old database survives the swap and answers every request with an error about an entity type it can no longer find, which is a site that looks broken immediately after a move that worked.

Drupal gets a larger CLI memory limit alongside it, because the rebuild is the thing that needs it: drush cr exhausts the 128M default part way through and leaves the site in exactly the state the rebuild was meant to clear.
@geodro geodro changed the title feat: declare the schema command, and wire Drupal through the file it reads feat: declare the schema and cache commands, the SQLite service, and wire Drupal through the file it reads Aug 8, 2026
…ired to"

SQLite is not a service. It is a file the project owns, with no container to run, no port and nothing to connect to, so declaring it under the services a framework can be wired to says the wrong thing about what it is.

It also reads badly on a binary that predates the engine side of this: a service block is a container to start, so an older lerd tells a SQLite project it could not start sqlite because no such service exists, on every env run.

This reverts commit 23ef8d9.
@geodro geodro changed the title feat: declare the schema and cache commands, the SQLite service, and wire Drupal through the file it reads feat: declare the schema and cache commands, and wire Drupal through the file it reads Aug 8, 2026
@geodro
geodro merged commit 7cfa300 into main Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant