ssch/typo3-debug-dump-pass
A lightweight TYPO3 extension that adds a debug dump compiler pass, letting developers use Symfony VarDumper-style dump output to inspect variables during development. Simple to install and handy for debugging TYPO3 sites.
This is a micro-package: it ships essentially one Symfony compiler pass that gets added to TYPO3's DI container so that static-analysis tooling can see a fully-populated container. Treat it as a build-time tool, not a runtime feature.
Minimal steps:
composer require --dev ssch/typo3-debug-dump-pass
composer dump-autoload
Prerequisites worth confirming before you bother:
saschaegerer/phpstan-typo3) and/or TYPO3-Rector in the same project. Without one of those, the package has no effect on your day-to-day work.Configuration/Services.php files for installed packages, so a Composer-installed extension is picked up automatically.Where to look first:
src/ — the whole package is one or two classes. Read the pass's process() method; that tells you exactly which service definitions it touches and whether it depends on kernel.debug.Configuration/Services.php (in the package) — shows whether it self-registers as a service or whether you must add it to your own container config.README.md — for a package this small, the README is the API reference; there is no docs site.First use case: you're raising PHPStan to level 6+ on an extension and keep getting mixed/“service not found” noise from container-resolved services (or from services that only exist under debug conditions). Install the package, clear the cache, rerun PHPStan with --no-result-cache, and diff the error count. That first diff is the entire value proposition in one command.
Dev-only, always. require-dev plus keeping it out of your production image build (composer install --no-dev) is the correct default. The pass changes how the container is built; you don't want that on live systems.
Register it where your project already registers compiler passes. In TYPO3 v12+ that's your sitepackage or project-level Configuration/Services.php:
$container->addCompilerPass(new \Ssch\Typo3DebugDumpPass\DebugDumpPass());
Check the package's own Services.php first — if it registers itself, adding it again is a no-op at best and a duplicate-pass headache at worst.
Gate it on context. Only enable in Development/CI so local container debugging stays sane:
if (\TYPO3\CMS\Core\Core\Environment::getContext()->isDevelopment()) {
$container->addCompilerPass(new DebugDumpPass());
}
Wire it into your analysis scripts, not into your deploy pipeline:
"scripts": {
"analyse": "rm -rf var/cache/code/core/* && php -d memory_limit=2G vendor/bin/phpstan analyse",
"analyse:baseline": "vendor/bin/phpstan analyse --generate-baseline"
}
Pair it with TYPO3-Rector upgrade branches. The workflow that actually pays off: cut an upgrade branch, run Rector, then run PHPStan with the pass enabled. The pass reduces container-related false positives, so the PHPStan run after the Rector run surfaces the real regressions instead of DI noise you're used to ignoring.
Use a baseline transition. Generate your PHPStan baseline without the pass, enable it, and confirm everything it “fixes” is genuinely a false positive. Then regenerate the baseline and commit it. This gives you a recorded, reviewable delta rather than an untraceable drop in error count.
CI pattern. A dedicated static-analysis job that installs with --dev, flushes the container cache, and runs PHPStan and Rector as separate steps with separate caches. Don't share the PHPStan result cache between jobs that toggle this pass on and off.
The container cache will lie to you. Toggling a compiler pass does nothing until TYPO3 rebuilds its container. After installing, enabling, or disabling: rm -rf var/cache/* (or vendor/bin/typo3 cache:flush, plus the typo3temp container artefact). Ninety percent of “the pass doesn't work” reports are stale cache.
Compiler passes run in ordered stages. If your pass needs to see definitions before they're pruned, you may need PassConfig::TYPE_BEFORE_REMOVING / TYPE_BEFORE_OPTIMIZATION rather than the default. If services disappear from the analysis after enabling the pass, that's the first knob to turn.
It cannot resurrect what Symfony already removed. Private, unused, and inlined services are gone by the time most passes run. If a service is missing from your analysis, the fix is usually an explicit public alias or a registerForAutoconfiguration, not this package.
PHPStan caching masks the change. PHPStan caches errors by file hash, not by container state. Always --no-result-cache (or wipe var/cache/phpstan) when you turn this on, otherwise a “no change” result means nothing.
Version coupling is the real risk. Three stars and zero dependents means you are the QA department: TYPO3 minors and Symfony DI changes can break the pass silently, and a broken pass typically manifests as fewer errors reported — which is the worst failure mode for static analysis. Pin the version in composer.json, keep it updated deliberately, and treat any drop in PHPStan error count after a dependency bump as a red flag to investigate rather than a win.
Debugging the container itself. There's no first-class debug:container in TYPO3, so when you need to inspect what the pass produced, write a throwaway script that boots the container and dumps it with Symfony's XmlDumper/PhpDumper, then grep for your service id. Keep that script out of the repo.
Extension points. The pass composes with others: add your own CompilerPassInterface implementation alongside it in the same Services.php to make project-specific conditional registrations visible to analysis. If the shipped class isn't final, subclassing to add project-specific service ids is a reasonable escape hatch — but wrap it in a project-local class rather than forking the package, so updates stay painless.
Don't let it into runtime debugging. If you also use it while chasing a real container error, remember you're looking at a modified container. Disable it before concluding anything about production behaviour.
How can I help you explore Laravel packages today?