All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
2.0.0 - 2026-05-06
Major release focused on dramatically reducing false positives in
architectural / SOLID analysis on framework projects (Laravel and Symfony).
The headline change is that --type=laravel is now a real, opinionated preset
instead of a near-no-op flag.
- Layer classification is now rule-based. The previous
(layer ⇒ namespace[] + suffix[])lookup is replaced by an ordered list of globLayerRuleobjects (first match wins).array_merge_recursiveis gone. CustomProjectTypeInterfaceimplementations must implement the newgetLayerRules()method (defaults provided inAbstractProjectType). *Actionis no longer classified asControllerin Laravel. It maps toApplication(use case). This eliminates ~12 spurious "Infrastructure → Controller" violations on a typical Laravel app using the Action pattern.Wiringis now a layer.ServiceProvider, container extensions and files under**\\Providers\\**are flagged asWiring, exempt from layer violation reporting and from DIP scoring. Their job is precisely to bind concrete classes from any layer, so the previous violations were noise.- DIP scope reduced to injected dependencies. Only
type_hint_param,type_hint_return, andtype_hint_propertycount toward the abstraction ratio.extends,trait,new,static_call,instanceof,catch,implements,const,useno longer pollute the metric. Old DIP scores are not comparable. - DIP whitelist by default. The Laravel preset excludes Eloquent
primitives, Carbon, Closure, facades, queue/bus traits, and OpenAPI
attributes from the DIP ratio. The Symfony preset excludes Doctrine ORM,
HttpFoundation, Form, Validator, Security, Twig, etc. This eliminates the
pathological case of e.g.
OrganizationControllerflagged with104/104 concrete dependencies. ProjectTypeInterfacegains 3 methods:getLayerRules(),getDipIgnoreList(),getWiringPatterns().AbstractProjectTypeprovides generic defaults so existing custom types still compile, but presets that want framework-aware behaviour must override them.SolidAnalyzer::analyze()andArchitectureAnalyzer::analyze()signatures changed.SolidAnalyzer::analyze(array $fileResults, array $dipIgnoreList = [], array $wiringClasses = [], array $classIgnores = []);ArchitectureAnalyzer::analyze(array $fileResults, ?ProjectTypeInterface $projectType = null, ?ProjectConfig $config = null).ProjectAnalyzerconstructor now requiresProjectConfigLoaderandBaselineManager. Symfony autowiring picks them up automatically.
phpquality.jsonproject configuration file at the project root. Schema (all keys optional):{ "layers": { "rules": [{ "match": "App\\Foo\\**", "layer": "Application" }] }, "wiring": { "patterns": ["**ServiceProvider"] }, "abstractionRatio": { "ignore": ["App\\Models\\**"] }, "ignore": { "violations": ["solid.dip:App\\Foo\\Bar"] }, "baseline": "phpquality.baseline.json" }layers.rulesis prepended to the framework preset (project rules win).wiring.patterns,abstractionRatio.ignore,ignore.violationsare unioned with framework defaults.@phpquality-ignoredocblock annotation on classes and interfaces:Codes:/** @phpquality-ignore solid.dip — wiring intentionnel */ final class FooService { … }
solid.srp,solid.dip,solid.isp,architecture.layer.- Baseline generation and application.
--generate-baseline=phpquality.baseline.jsonwrites a hash-keyed list of all current violations and exits successfully (does not fail-on-violation).--baseline=phpquality.baseline.jsonfilters violations whose hash is in the baseline. The summary exposessuppressedByBaselineand warns aboutobsoleteBaselineEntries(entries that no longer match anything → regenerate).
- New CLI options:
--config,--baseline,--generate-baseline. - New services:
PhpQuality\Config\ProjectConfigLoader,PhpQuality\Config\BaselineManager,PhpQuality\Config\ProjectConfig,PhpQuality\Config\LayerRule,PhpQuality\Analyzer\Ast\IgnoreAnnotationParser.
Most users only need to run the new version: false positives drop on their own. If you previously had a CI policy on the violation counts, expect those counts to decrease.
If you have a custom ProjectTypeInterface implementation:
- Have it extend
AbstractProjectType(gets the 3 new methods for free), OR - Implement
getLayerRules(),getDipIgnoreList(),getWiringPatterns().
If you want to keep some violations in your reports while you migrate, pin
them via --generate-baseline and commit the baseline file. Subsequent runs
with --baseline=… will only show new violations.
1.6.0 - 2026-03-26
- Symfony Profiler panel showing PHP quality metrics for files used during request
CallstackTracerto capture controller informationDependencyTreeAnalyzerfor static analysis of controller imports and dependencies- Debug information in profiler panel (mode, project directory, analyzed files count)
- Profiler now analyzes controller dependency tree via
usestatements instead of all included files - Improved exclude paths filtering (relative to project root)
- DataCollector service visibility for Symfony Profiler integration
- FileAnalyzer service marked as public for dependency injection
1.5.0 - 2026-03-26
- Configuration file support for quality thresholds via
config/packages/php_quality.yaml - Symfony Profiler integration with dedicated panel showing metrics for files loaded during request
ThresholdsConfigDTO for threshold management with framework defaults merging- Symfony Flex recipe for automatic bundle configuration on install
- Development environment config enabling profiler by default
- Thresholds can now be overridden per-project while keeping framework-specific defaults for non-configured values
1.4.1 - 2026-03-26
- Memory limit handling for large project analysis
1.4.0 - 2026-03-26
- Multi-architecture Docker build support (amd64 + arm64)
- Docker build with correct package name
1.3.0 - 2026-03-25
- Interactive wizard mode for command configuration (
--wizardor-woption)
1.2.2 - 2026-03-25
- JSON report generation with proper error handling
1.2.1 - 2026-03-25
- Twig template paths to use bundle namespace
1.2.0 - 2026-03-25
- Symfony Bundle architecture (package renamed to
amoifr/phpquality-bundle) - README translated to English
- Refactored entire codebase to Symfony Bundle structure
- Package renamed from standalone tool to Symfony bundle
1.1.0 - 2026-03-25
- Code Coverage Analysis feature from Clover XML reports (
--coverageoption) - Architecture Analysis inspired by Deptrac/PHP Insights (layer detection, SOLID principles)
- Hall of Fame/Shame feature using git blame (
--git-blameoption) - Comprehensive PHPUnit test suite
- Translations for coverage and recommendations sections
- 17 language translations for reports
- Git blame analysis now optional (disabled by default)
- Docker Hub image name to
amoifr13/phpquality
1.0.0 - 2026-03-19
- Initial release of PhpQuality PHP Code Analyzer
- Cyclomatic Complexity (CCN) analysis per method and file
- Maintainability Index (MI) calculation with ratings (A-F)
- Lines of Code metrics (LOC, LLOC, CLOC, comment ratio)
- Halstead metrics (Volume, Difficulty, Effort, Bugs)
- Lack of Cohesion of Methods (LCOM) analysis
- HTML report generation with interactive charts
- Console report output with tables and summaries
- Multiple project type detection (Symfony, Laravel, WordPress, Magento, Drupal, etc.)
- Docker support for containerized analysis
- GitHub Actions workflow for Docker image publishing
- Allow running Docker container with any user (
--userflag)