pluswerk/grumphp-config
A GrumPHP configuration package for Laravel/PHP projects that auto-generates grumphp.yml, rector.php, phpstan.neon, and a baseline, pulling in project-specific resources as needed. Override any settings directly in the generated grumphp.yml.
Installation:
composer require --dev andersundsehr/grumphp-config
This auto-generates (or updates) the shared config set:
grumphp.yml (GrumPHP task configuration — shared across all projects using the package)rector.php (Rector rules)phpstan.neon (PHPStan configuration)phpstan-baseline.neon (Baseline for existing code)First Use Case: Run GrumPHP on your Laravel project to catch issues early:
./vendor/bin/grumphp run
composer_validate_autoload (new in 11.2.0) — verifies your composer.json autoload section is valid and that the generated autoloader actually matches your filesystem (missing classes, stale PSR-4 mappings, classmap drift).Where to Look First:
grumphp.yml: Override tasks/rules (e.g., exclude vendor/, add Laravel-specific paths, disable composer_validate_autoload if you don't want it locally).rector.php: Adjust Rector rules (e.g., skip rules that fight Laravel conventions).phpstan-baseline.neon: Update baselines after running Rector.composer_validate_autoload task is added to the shared task configuration. After composer update, re-run GrumPHP once locally — if your repo has a pre-existing autoload problem it will now surface as a commit-blocking failure. Fix with composer dump-autoload (and composer validate) before committing.Laravel-Specific Customization:
# grumphp.yml
exclude_file_patterns:
- "vendor/"
- "bootstrap/cache/*"
- "storage/framework/*"
tasks:
phpcsfixer:
config: ".php-cs-fixer.dist.php" # Replace with Laravel Pint config
Integration with Laravel CI:
.github/workflows/laravel.yml:
- name: Run GrumPHP
run: ./vendor/bin/grumphp run
- uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
Autoload Validation (11.2.0+):
composer_validate_autoload is now part of the shared config, so it runs wherever grumphp run runs. Use it as the cheap first gate in CI — it catches broken PSR-4 maps before PHPStan/Rector waste minutes on files that can't even be autoloaded.composer.json autoload.psr-4, or a classmap pointing at renamed/deleted files.composer dump-autoload --optimize / --classmap-authoritative in deploy, this task keeps local/CI in sync with that expectation.# grumphp.yml (local override)
tasks:
composer_validate_autoload: ~
Rector Workflow for Laravel:
tasks:
rector:
config: "rector.php"
dry_run: false # Auto-fix on commit
--parallel:
./vendor/bin/rector process src --parallel
PHPStan for Laravel:
phpstan.neon to include Laravel-specific rules:
includes:
- vendor/larastan/larastan/extension.neon
tasks:
phpstan:
configuration: "phpstan.neon"
triggered_by: ["php"]
ignore_patterns: ["tests/*"]
Daily Development:
git add . && ./vendor/bin/grumphp run
composer dump-autoload before GrumPHP — otherwise the new composer_validate_autoload task fails for a reason unrelated to your change.Pre-Release:
./vendor/bin/rector process src --dry-run
./vendor/bin/phpstan analyse --generate-baseline
composer validate --strict && composer dump-autoload --optimize
Onboarding New Devs:
grumphp.yml overrides in CONTRIBUTING.md:
## Code Quality
Run `composer require --dev andersundsehr/grumphp-config` to set up GrumPHP.
Override rules in `grumphp.yml` as needed.
Note: `composer_validate_autoload` is enabled by default since v11.2.0.
Path Issues:
__DIR__ (fixed in v10.2.7+), but older versions may break in subdirectories.getcwd() or update paths manually:
# grumphp.yml
paths:
- "src/"
- "app/"
PHPStan Conflicts:
PSR-4 autoloading may cause PHPStan to miss files.# phpstan.neon
parameters:
paths:
- app
- src
composer_validate_autoload Surprises (11.2.0):
autoload-dev mapping, a files entry pointing at a removed helper, or a stale vendor/composer/autoload_classmap.php after branch switches.composer dump-autoload, then re-run. If it's a genuine mapping gap, extend composer.json:
{
"autoload": { "psr-4": { "App\\": "app/" } },
"autoload-dev": { "psr-4": { "Tests\\": "tests/" } }
}
composer validate for the rest of composer.json (name, license, version constraints). Keep both.Rector Over-Aggressiveness:
// rector.php
return static::configureRules([
\Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorRector::class => false,
]);
DDEV Environments:
DDEV_EXEC rule (enabled by default in v10.2.6+):
# grumphp.yml
parameters:
tasks.phpunit.env:
- "DDEV_EXEC"
Baseline Management:
phpstan-baseline.neon after Rector runs.composer.json:
"scripts": {
"post-rector": "phpstan analyse --generate-baseline"
}
GrumPHP Fails Silently:
--verbose:
./vendor/bin/grumphp run --verbose
~/.cache/grumphp/.Isolate the New Autoload Task:
./vendor/bin/grumphp run --tasks=composer_validate_autoload -vvv
Reproduce outside GrumPHP to confirm:
composer validate --no-check-publish && composer dump-autoload --no-scripts -o
PHPStan Errors:
./vendor/bin/phpstan analyse --level=max app/Http/Controllers/HomeController.php
Rector Hangs:
--parallel or limit files:
./vendor/bin/rector process src/ --parallel --max-processes=4
Custom Tasks:
laravel-pint):
# grumphp.yml
tasks:
laravel-pint:
command: "php artisan pint"
on_fail: fail
Toggling Shared Tasks:
composer_validate_autoload in the shared config, disable it per-project rather than deleting it from the generated file (it will come back on the next update):
# grumphp.yml
tasks:
composer_validate_autoload: ~
Dynamic Configs:
grumphp.yml:
parameters:
tasks.phpunit.env:
- "DB_CONNECTION=${DB_CONNECTION:-mysql}"
Git Hooks:
post-commit (or better, pre-commit) hooks:
echo "./vendor/bin/grumphp run" >> .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
CI-Specific Overrides:
# grumphp.yml (local)
tasks:
phpstan: ~
# grumphp.ci.yml (CI-only)
tasks:
phpstan:
level: max
Start Strict, Then Relax:
level: max in PHPStan, then adjust baselines incrementally.Order Your Gates Cheap → Expensive:
composer_validate_autoload fail first (it's fast), then PHP-CS-Fixer, then Rector, then PHPStan. A broken autoload makes every downstream task's output noise.Exclude Tests from Heavy Tasks:
# grumphp.yml
exclude_file_patterns:
- "tests/*"
Monitor Performance:
# .github/workflows/laravel.yml
- uses: actions/cache@v3
with:
path: ~/.cache/grumphp
key: ${{ runner.os }}-grumphp-${{ hashFiles('**/composer.lock') }}
Pin and Review on Upgrade:
grumphp.yml after composer update.Document Overrides:
CODE_QUALITY.md explaining custom rules and why each shared task is disabled, so new devs don't re-enable something that breaks the build.How can I help you explore Laravel packages today?