Composer Scripts & Hooks
debt(d7/e3/b3/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no' — there's no linter or SAST tool that flags missing Composer scripts. The code_pattern describes symptoms (long CI commands, different developer invocations) that only surface through code review or observing CI drift. Composer itself doesn't warn about missing scripts.
Closest to 'simple parameterised fix' (e3). The quick_fix shows defining scripts in composer.json is straightforward — adding a scripts section with test, lint, analyse entries. However, it's not quite a one-line patch (e1) since you need to define multiple scripts and potentially update CI pipelines to use them, touching a few files.
Closest to 'localised tax' (b3). Missing Composer scripts creates a localised tax where each developer and CI pipeline may invoke tools differently, but this doesn't fundamentally shape the architecture. The applies_to shows web/cli contexts, meaning moderate reach, but the burden stays contained to build/dev tooling rather than runtime code. Once scripts are defined, the tax is paid and the system benefits.
Closest to 'notable trap' (t5). The misconception field explicitly states developers think Composer scripts are 'only useful for running tests' when they can automate code generation, asset compilation, migrations, and any shell command. This is a documented gotcha that most PHP devs eventually learn, but the narrow mental model leads teams to miss the full task-runner capability built into every project.
Also Known As
TL;DR
Explanation
Composer scripts are shell commands or PHP callables in the scripts key of composer.json, executed automatically on lifecycle events (post-install-cmd, post-update-cmd, post-autoload-dump) or manually with composer run. Common uses: clearing caches, running migrations, generating IDE helper files, and compiling assets. Security concern: scripts from third-party packages run with the same privileges as the Composer process — always audit composer.json of new dependencies before running composer install in CI. Use --no-scripts to disable all scripts when trust is uncertain, such as when first evaluating a package.
Watch Out
Common Misconception
Why It Matters
Common Mistakes
- Not defining scripts for common tasks — developers run different commands and the team drifts.
- Scripts that run dev-only tools (phpstan, phpcs) without guarding against --no-dev production installs.
- Forgetting to chain scripts with @script syntax — duplicating command lists in multiple script entries.
- Not documenting custom scripts — composer run without arguments lists available scripts, but descriptions help.
Code Examples
// No scripts defined — every dev runs slightly different commands:
{
"require": {"php": ">=8.1"},
"require-dev": {"phpunit/phpunit": "^10"}
// Missing: scripts.test, scripts.lint, scripts.analyse
}
// composer.json scripts — automate common tasks
{
"scripts": {
"test": "phpunit --colors=always",
"lint": "phpcs --standard=PSR12 src/ tests/",
"lint:fix": "phpcbf --standard=PSR12 src/ tests/",
"analyse": "phpstan analyse src/ --level=6",
"audit": "composer audit",
"ci": ["@lint", "@analyse", "@test", "@audit"]
},
"scripts-descriptions": {
"test": "Run PHPUnit test suite",
"ci": "Run full CI pipeline locally"
}
}
// Run:
// $ composer test
// $ composer ci
// $ composer lint:fix