Summary
bin/composer-post-install-script.php creates the local autoload config from its .dist template, but composer.json registers it under post-update-cmd only:
"post-update-cmd": [
"php bin/composer-post-install-script.php"
],
There is no post-install-cmd entry, so despite its name the script never runs on a plain composer install.
Why it currently appears to work
composer.lock is listed in .gitignore, so a fresh clone has no lock file and composer install degrades into an update — which dispatches post-update-cmd and creates the file. The behaviour depends on the lock file being absent.
When it breaks
Any fresh checkout that does have a composer.lock, because that is a genuine install and the hook never fires:
- deployment pipelines that ship a lock file and run
composer install --no-dev
- any team that stops gitignoring
composer.lock, which is the usual recommendation for applications (this package is "type": "project")
Impact
config/config.php globs the autoload directory, so a missing local config is not an error — it simply does not match, and aggregation continues silently.
However application.url and routes.page (about, who-we-are) are defined only in the local config. No *.global.php file provides either key. The result is an application with no configured base URL and no page routes, with nothing pointing at the cause.
Suggested fix
Register the script under post-install-cmd as well, so the hook matches its name and lock-based installs are covered:
"post-install-cmd": [
"php bin/composer-post-install-script.php"
],
"post-update-cmd": [
"php bin/composer-post-install-script.php"
],
The script already no-ops when the destination exists (is_readable() check), so registering it on both events is safe.
Note
The README side of this — it currently tells the reader to set $baseUrl in the local config without mentioning that the file must be created first — is being handled separately in a README fix pass.
Summary
bin/composer-post-install-script.phpcreates the local autoload config from its.disttemplate, butcomposer.jsonregisters it underpost-update-cmdonly:There is no
post-install-cmdentry, so despite its name the script never runs on a plaincomposer install.Why it currently appears to work
composer.lockis listed in.gitignore, so a fresh clone has no lock file andcomposer installdegrades into an update — which dispatchespost-update-cmdand creates the file. The behaviour depends on the lock file being absent.When it breaks
Any fresh checkout that does have a
composer.lock, because that is a genuine install and the hook never fires:composer install --no-devcomposer.lock, which is the usual recommendation for applications (this package is"type": "project")Impact
config/config.phpglobs the autoload directory, so a missing local config is not an error — it simply does not match, and aggregation continues silently.However
application.urlandroutes.page(about,who-we-are) are defined only in the local config. No*.global.phpfile provides either key. The result is an application with no configured base URL and no page routes, with nothing pointing at the cause.Suggested fix
Register the script under
post-install-cmdas well, so the hook matches its name and lock-based installs are covered:The script already no-ops when the destination exists (
is_readable()check), so registering it on both events is safe.Note
The README side of this — it currently tells the reader to set
$baseUrlin the local config without mentioning that the file must be created first — is being handled separately in a README fix pass.