Releases: Phauthentic/phpstan-rules
1.9.0 New rules, increased test coverage and bug fixes
🎉 New Features
✨ New Rule: Property Must Match Rule
Enforce Property Conventions on Classes
- Class:
Phauthentic\PHPStanRules\Architecture\PropertyMustMatchRule - Purpose: Validates that classes matching specified patterns have properties with expected names, types, and visibility scopes
- Key Features:
- Required Properties: Enforce that matching classes must have certain properties
- Type Validation: Check property types including support for union types (
int|string) and intersection types (Foo&Bar) - Visibility Enforcement: Ensure properties use the correct visibility (
public,protected,private) - Nullable Support: Optionally accept both a type and its nullable variant (e.g.,
intand?int) - Flexible Matching: Uses regex patterns to target specific classes
- Configuration: Supports
propertyPatternsparameter withclassPatternandpropertiessub-configuration - Error Messages:
Class {class} must have property ${name}.(when required property is missing)Property {class}::${name} should be of type {expected}, {actual} given.(type mismatch)Property {class}::${name} must be {visibility}.(visibility mismatch)
Configuration Example:
services:
-
class: Phauthentic\PHPStanRules\Architecture\PropertyMustMatchRule
arguments:
propertyPatterns:
-
classPattern: '/^App\\Entity\\.*$/'
properties:
-
name: 'id'
type: 'int'
visibilityScope: 'private'
required: true
-
name: 'createdAt'
type: 'DateTimeImmutable'
visibilityScope: 'private'
required: true
nullable: true
tags:
- phpstan.rules.rule✨ New Rule: Forbidden Accessors Rule
Enforce Encapsulation and the "Tell, Don't Ask" Principle
- Class:
Phauthentic\PHPStanRules\Architecture\ForbiddenAccessorsRule - Purpose: Forbids public and/or protected getters (
getXxx()) and setters (setXxx()) on classes matching specified patterns - Key Features:
- Configurable Accessor Types: Independently control whether getters, setters, or both are forbidden
- Visibility Control: Choose which visibility levels to check (
public,protected) - Pattern Matching: Uses regex patterns against fully qualified class names
- Anonymous Class Safe: Properly skips anonymous classes
- Configuration: Supports
classPatterns,forbidGetters,forbidSetters, andvisibilityparameters - Error Messages:
Class {class} must not have a {visibility} getter method {method}().Class {class} must not have a {visibility} setter method {method}().
Configuration Example:
services:
-
class: Phauthentic\PHPStanRules\Architecture\ForbiddenAccessorsRule
arguments:
classPatterns:
- '/^App\\Domain\\.*Entity$/'
- '/^App\\Domain\\.*ValueObject$/'
forbidGetters: true
forbidSetters: true
visibility:
- public
tags:
- phpstan.rules.ruleUse Cases:
- Enforce immutability on domain entities by forbidding setters
- Apply the "Tell, Don't Ask" principle by forbidding both getters and setters
- Restrict only public accessors while allowing protected ones for inheritance
✨ New Rule: Forbidden Static Methods Rule
Prevent Static Method Calls
- Class:
Phauthentic\PHPStanRules\Architecture\ForbiddenStaticMethodsRule - Purpose: Forbids specific static method calls matching regex patterns to encourage dependency injection and testability
- Key Features:
- Multi-Level Granularity: Supports namespace-level, class-level, and method-level patterns
- Keyword Resolution: Resolves
self,static, andparentkeywords to actual class names before matching - Dynamic Call Safe: Skips dynamic class names (
$class::method()) and dynamic method names (Class::$method())
- Configuration: Supports
forbiddenStaticMethodsparameter with an array of regex patterns matchingFQCN::methodName - Error Messages:
Static method call "{call}" is forbidden.
Configuration Example:
services:
-
class: Phauthentic\PHPStanRules\Architecture\ForbiddenStaticMethodsRule
arguments:
forbiddenStaticMethods:
- '/^App\\Legacy\\.*::.*/' # Namespace-level: all legacy static calls
- '/^App\\Utils\\StaticHelper::.*/' # Class-level: all methods on StaticHelper
- '/^DateTime::createFromFormat$/' # Method-level: specific method only
tags:
- phpstan.rules.rule✨ New: ClassNameResolver Trait
Reusable Utilities for FQCN Resolution
- Trait:
Phauthentic\PHPStanRules\Architecture\ClassNameResolver - Purpose: Extracts common fully qualified class name resolution and type conversion utilities into a reusable trait
- Key Methods:
resolveFullClassName()— Builds the FQCN from aClass_orInterface_node and scope; returnsnullfor anonymous classesgetTypeAsString()— Converts type nodes (Identifier,Name,NullableType,UnionType,IntersectionType) to their string representationmatchesAnyPattern()— Checks if a string matches any of the given regex patternsnormalizeClassName()— Removes the leading backslash from a class name
✨ New: Interactive Rule Config Builder
- File:
rule-builder.html - Purpose: An interactive HTML tool for building PHPStan rule configurations visually, making it easier to create correct
phpstan.neonconfiguration without memorizing all parameters
🔧 Code Quality Improvements
🏗️ Refactored Rules to Use ClassNameResolver Trait
Multiple existing rules were refactored to use the new ClassNameResolver trait, reducing code duplication and improving consistency:
- AttributeRule — Replaced inline FQCN resolution with
resolveFullClassName() - CatchExceptionOfTypeNotAllowedRule — Added class name normalization for robust comparison (leading backslash handling)
- ClassMustBeFinalRule — Simplified to use
resolveFullClassName()andmatchesAnyPattern() - ClassMustBeReadonlyRule — Simplified to use
resolveFullClassName()andmatchesAnyPattern() - ClassMustHaveSpecificationDocblockRule — Replaced private
matchesPatterns()with trait'smatchesAnyPattern() - MethodMustReturnTypeRule — Replaced private
getTypeAsString()with trait version; now uses FQCN for method matching - MethodSignatureMustMatchRule — Replaced private
getTypeAsString()with trait version; now uses FQCN for method matching
🔒 Improved Anonymous Class Handling
All class-level rules now properly skip anonymous classes (classes without names) via the resolveFullClassName() method returning null, preventing false positives and potential errors.
✅ Constructor Parameter Validation
Both PropertyMustMatchRule and ForbiddenAccessorsRule validate constructor parameters at instantiation time, throwing InvalidArgumentException for invalid configurations (empty patterns, invalid visibility values).
🔧 Regex Error Handling
PropertyMustMatchRule and ForbiddenAccessorsRule now properly handle preg_match errors, throwing InvalidArgumentException with descriptive messages when an invalid regex pattern is provided.
📦 Dependency Updates
- Updated
phpunit/phpunitfrom^12.0to^12.5.8
📚 Documentation Improvements
📚 New Documentation Files
- Forbidden Accessors Rule: Complete documentation with examples for forbidding getters, setters, or both at configurable visibility levels
- Forbidden Dependencies Rule: Dedicated documentation for the renamed rule with FQCN checking, allowed dependencies, and a Mermaid flowchart explaining the allow/forbid logic
- Forbidden Static Methods Rule: Full documentation covering namespace-level, class-level, and method-level pattern granularity, including
self/static/parenthandling - Property Must Match Rule: Comprehensive documentation with examples for required properties, optional validation, and nullable types
📚 Updated Documentation
- README.md: Added Forbidden Accessors Rule, Forbidden Dependencies Rule, Forbidden Static Methods Rule, and Property Must Match Rule to the Architecture Rules list; marked Dependency Constraints Rule as deprecated
- docs/Rules.md: Added overview sections and full configuration examples for all new rules
✅ New Test Coverage
New Test Files
- PropertyMustMatchRuleTest: Core functionality tests for property name, type, and required validation
- PropertyMustMatchRuleNullableTest: Tests for nullable type matching
- PropertyMustMatchRuleIntersectionTypeTest: Tests for intersection type support
- PropertyMustMatchRuleInvalidVisibilityTest: Tests for invalid visibility validation
- PropertyMustMatchRuleInvalidRegexTest: Tests for invalid regex pattern handling
- PropertyMustMatchRuleExceptionsTest: Tests for constructor validation
- ForbiddenAccessorsRuleTest: Core functionality tests
- ForbiddenAccessorsRuleGettersOnlyTest: Tests for forbidding only getters
- **Forb...
Version 1.8.0
🎉 New Features
✨ New Rule: Attribute Rule
New Rule for PHP 8+ Attribute Validation
- Class:
Phauthentic\PHPStanRules\Architecture\AttributeRule - Purpose: Validates PHP 8+ attributes on classes, methods, and properties using regex patterns
- Key Features:
- Allowed Attributes: Restrict which attributes can be used on matching targets
- Forbidden Attributes: Prevent specific attributes from being used
- Required Attributes: Enforce that certain attributes must be present
- Flexible Targeting: Match classes, methods, and properties using regex patterns
- Combined Rules: All three rule types can be applied simultaneously to the same target
- Configuration: Supports three optional sections:
allowed- Define which attributes are permitted (whitelist)forbidden- Define which attributes are prohibited (blacklist)required- Define which attributes must be present
Configuration Example:
services:
-
class: Phauthentic\PHPStanRules\Architecture\AttributeRule
arguments:
config:
allowed:
# Controllers can only have Route and Cache attributes on methods
-
classPattern: '/^App\\Controller\\.*/'
methodPattern: '/.*Action$/'
attributes:
- '/^Symfony\\Component\\Routing\\Annotation\\Route$/'
- '/^Symfony\\Component\\HttpKernel\\Attribute\\Cache$/'
forbidden:
# Domain layer cannot have framework attributes
-
classPattern: '/^App\\Domain\\.*/'
methodPattern: '/.*/'
attributes:
- '/^Symfony\\.*/'
- '/^Doctrine\\.*/'
required:
# All action methods must have a Route attribute
-
classPattern: '/^App\\Controller\\.*/'
methodPattern: '/.*Action$/'
attributes:
- '/^Symfony\\Component\\Routing\\Annotation\\Route$/'
tags:
- phpstan.rules.ruleUse Cases:
- Enforce that controller actions only use approved routing attributes
- Prevent framework-specific attributes in your domain layer (clean architecture)
- Ensure entity properties only use Doctrine ORM mapping attributes
- Require specific attributes on classes, methods, or properties
- Combine all three rule types for comprehensive attribute validation
Error Messages:
- Forbidden:
Attribute {attribute} is forbidden on {type} {name}. - Not in allowed list:
Attribute {attribute} is not in the allowed list for {type} {name}. Allowed patterns: {patterns} - Missing required:
Missing required attribute matching pattern {pattern} on {type} {name}.
📚 Updated README
- Added Attribute Rule to the Architecture Rules list
- Sorted Architecture Rules list alphabetically for better discoverability
🚀 Migration Guide
For Existing Users
No Action Required! All existing configurations continue to work without any changes. The new Attribute Rule is opt-in and requires explicit configuration.
For New Attribute Rule
To use the new Attribute Rule, add the configuration to your phpstan.neon:
services:
-
class: Phauthentic\PHPStanRules\Architecture\AttributeRule
arguments:
config:
allowed:
-
classPattern: '/^App\\Controller\\.*/'
attributes:
- '/^Symfony\\Component\\Routing\\Annotation\\Route$/'
forbidden:
-
classPattern: '/^App\\Domain\\.*/'
attributes:
- '/^Symfony\\.*/'
required:
-
classPattern: '/^App\\Entity\\.*/'
attributes:
- '/^Doctrine\\ORM\\Mapping\\Entity$/'
tags:
- phpstan.rules.ruleFull Changelog: 1.7.0...1.8.0
1.7.0
Release Notes - Version 1.7.0
🎉 New Features
✨ Renamed DependencyConstraintsRule to ForbiddenDependenciesRule
Breaking Change (with full Backward Compatibility!)
- New Class:
Phauthentic\PHPStanRules\Architecture\ForbiddenDependenciesRule - Deprecated Class:
Phauthentic\PHPStanRules\Architecture\DependencyConstraintsRule - Purpose: The new name better reflects the rule's purpose - forbidding specific dependencies between namespaces
- Migration: The old
DependencyConstraintsRuleclass is kept for backward compatibility but will be removed in a future major version. Please update your configuration to useForbiddenDependenciesRuleinstead.
✨ New allowedDependencies Feature for ForbiddenDependenciesRule
Enhancement: Whitelist Override for Forbidden Dependencies
- Class:
Phauthentic\PHPStanRules\Architecture\ForbiddenDependenciesRule - Purpose: Allows creating a "forbid everything except X" pattern without complex regex
- Key Features:
- New
allowedDependenciesparameter that overrides forbidden dependencies - Dependencies matching both a forbidden pattern and an allowed pattern will be allowed
- Enables clean domain layer isolation while permitting specific exceptions
- New
- Configuration: New optional parameter:
allowedDependencies(array, default:[]) - Whitelist patterns that override forbidden dependencies
- Use Case Example: Forbid all namespaced dependencies in the domain layer, except for
App\Shared,App\Capability, andPsr\*:
services:
-
class: Phauthentic\PHPStanRules\Architecture\ForbiddenDependenciesRule
arguments:
forbiddenDependencies: [
'/^App\\Capability\\.*\\Domain$/': [
'/.*\\\\.*/' # Match anything with a backslash (namespaced)
]
]
checkFqcn: true
allowedDependencies: [
'/^App\\Capability\\.*\\Domain$/': [
'/^App\\Shared\\/',
'/^App\\Capability\\/',
'/^Psr\\/'
]
]
tags:
- phpstan.rules.rule✨ Required Methods Feature for MethodSignatureMustMatchRule
Enhancement: Enforce Method Implementation in Matching Classes
- Class:
Phauthentic\PHPStanRules\Architecture\MethodSignatureMustMatchRule - Purpose: Ensures that classes matching a pattern actually implement a required method with the specified signature
- Key Features:
- New
requiredparameter (boolean, default:false) - When
true, enforces that matching classes must implement the specified method - Reports clear error messages with the expected signature when a required method is missing
- New
- Use Case Example: Ensure all controllers implement an
executemethod:
services:
-
class: Phauthentic\PHPStanRules\Architecture\MethodSignatureMustMatchRule
arguments:
signaturePatterns:
-
pattern: '/^.*Controller::execute$/'
minParameters: 1
maxParameters: 1
signature:
-
type: 'Request'
pattern: '/^request$/'
visibilityScope: 'public'
required: true
tags:
- phpstan.rules.rule🔧 Code Quality Improvements
🏗️ PHPStan Level 8 Compliance
- Enhancement: All rule classes now pass PHPStan level 8 analysis
- Improvements:
- Updated error handling to use
IdentifierRuleErrorinstead of genericRuleError - Enhanced method signatures with explicit type hints for better clarity and type safety
- Added parameter type annotations in
processNodemethods for improved documentation - Removed unnecessary instance checks in
processNodemethods to streamline logic - Improved error handling and reporting consistency across all rules
- Updated error handling to use
🔧 CI Pipeline Enhancements
- New Jobs: Added dedicated PHPStan and PHPCS jobs to CI configuration
- Configuration:
- Both jobs run on Ubuntu 24.04 with PHP 8.4
- Ensures static analysis and coding standards are enforced on every push and pull request
- Benefits:
- Catches type errors and coding standard violations early
- Maintains consistent code quality across contributions
📚 Documentation Improvements
📚 New Extending Rules Documentation
- New File:
docs/ExtendingRules.md - Purpose: Comprehensive guide for creating domain-specific, self-documenting rules by extending base rules
- Contents:
- Benefits of extending rules (self-documenting code, reusability, IDE support, testability)
- Multiple examples including:
- Forbidding
DateTimein module namespaces - Enforcing final classes in domain layer
- Preventing legacy namespace usage
- Forbidding
- How to customize error messages and identifiers
- Best practices for organizing custom rules
📚 Updated README
- New Section: "Domain Specific Rules / Extending Rules" with link to new documentation
- Enhancement: Clearer explanation of the extensibility features
📚 Enhanced Dependency Constraints Rule Documentation
- Deprecation Notice: Clear warning about the renamed class
- New Section: Detailed documentation for the
allowedDependenciesparameter - Diagram: Added Mermaid flowchart explaining the allow/forbid logic
- Examples: Comprehensive configuration examples for the whitelist feature
📚 Enhanced Method Signature Must Match Rule Documentation
- New Section: Documentation for the
requiredparameter - Example: Complete configuration example for enforcing required methods
🚀 Migration Guide
For Existing Users
No immediate action required! All existing configurations continue to work without changes due to backward compatibility.
Recommended Updates
-
Rename DependencyConstraintsRule to ForbiddenDependenciesRule:
Before:
class: Phauthentic\PHPStanRules\Architecture\DependencyConstraintsRule
After:
class: Phauthentic\PHPStanRules\Architecture\ForbiddenDependenciesRule
-
Consider using allowedDependencies for cleaner "forbid everything except X" patterns instead of complex negative regex.
-
Consider using the required parameter for MethodSignatureMustMatchRule to enforce method implementation in matching classes.
💡 Why This Matters
Clearer Naming
The rename from DependencyConstraintsRule to ForbiddenDependenciesRule makes the rule's purpose immediately clear - it forbids specific dependencies. This follows the principle of self-documenting code.
Flexible Dependency Control
The new allowedDependencies feature provides a powerful yet simple way to implement "whitelist" patterns. Instead of crafting complex negative lookahead regex patterns, you can now simply:
- Forbid everything with a broad pattern
- Allow specific exceptions with simple patterns
This significantly simplifies configuration for common architectural patterns like clean architecture domain layers.
Enforce Architectural Contracts
The required parameter for MethodSignatureMustMatchRule enables enforcement of architectural contracts. For example, ensuring all controllers implement a specific execute method guarantees consistency across your application without relying on abstract classes or interfaces.
Extensibility
The new documentation on extending rules encourages creating domain-specific, self-documenting rules. A class named DomainClassesMustBeFinalRule is far more readable than a configuration block with regex patterns.
This release significantly improves the usability and flexibility of the PHPStan rules while maintaining 100% backward compatibility. We recommend updating to the new class names and exploring the new features to improve your architectural enforcement.
Full Changelog: 1.6.0...1.7.0
Enhanced Max Line Length Rule
Release Notes - Version 1.6.0
🎉 New Features
✨ Enhanced Max Line Length Rule
Enhancement: Flexible Line Type Ignoring
-
Class:
Phauthentic\PHPStanRules\CleanCode\MaxLineLengthRule -
Purpose: Extended to support ignoring multiple types of lines beyond just use statements, providing more granular control over line length checking
-
Key Features:
- New Array-Based API: Introduced
ignoreLineTypesparameter for flexible configuration - Multiple Line Types: Support for ignoring use statements, namespace declarations, and docblocks
- Backward Compatible: Existing
ignoreUseStatementsparameter continues to work unchanged - Selective Control: Choose which line types to ignore independently
- New Array-Based API: Introduced
-
Supported Line Types:
useStatements- Ignore lines containingusestatements (e.g.,use Some\Very\Long\Namespace\Path\ClassName;)namespaceDeclaration- Ignore lines containingnamespacedeclarations (e.g.,namespace App\Some\Very\Long\Namespace\Path;)docBlocks- Ignore lines that are part of docblock comments (e.g.,/** This is a very long docblock comment that exceeds the line length limit */)
-
Configuration: Supports new optional parameter:
ignoreLineTypes(array, default:[]) - Array of line types to ignore with boolean valuesignoreUseStatements(boolean, default:false) - Maintained for backward compatibility, takes precedence when set
-
Backward Compatibility:
- The existing
ignoreUseStatementsparameter remains fully functional - When both
ignoreUseStatementsandignoreLineTypes['useStatements']are set,ignoreUseStatementstakes precedence - All existing configurations continue to work without modification
- The existing
📚 Documentation Improvements
📚 Enhanced Max Line Length Rule Documentation
-
Comprehensive Examples: Added detailed configuration examples for:
- New array-based API (recommended approach)
- Legacy parameter usage (backward compatible)
- Selective line type ignoring
- Combined configurations
-
Parameter Documentation: Complete documentation of all parameters including:
maxLineLength- Maximum allowed line lengthexcludePatterns- File exclusion patternsignoreUseStatements- Legacy parameter for backward compatibilityignoreLineTypes- New array-based configuration option
-
Use Cases Section: Examples showing:
- Ignoring only use statements
- Ignoring namespace declarations and docblocks
- Ignoring all supported line types
- Combining with file exclusions
🚀 Migration Guide
For Existing Users
No Action Required! All existing configurations continue to work without any changes. The new ignoreLineTypes parameter is optional and disabled by default, so your current setup will behave exactly as before.
For New Configurations
Recommended: Use the new array-based API for better flexibility:
ignoreLineTypes:
useStatements: true
namespaceDeclaration: true
docBlocks: trueLegacy: The ignoreUseStatements parameter still works and is fully supported:
ignoreUseStatements: true💡 Why This Matters
The previous version only supported ignoring use statements. Many codebases have long namespace declarations or detailed docblocks that exceed line length limits but are acceptable for readability. This release provides the flexibility to ignore these line types while still enforcing line length limits for actual code logic.
Before (1.5.1): Only use statements could be ignored
After (1.6.0): You can now ignore:
- Use statements
- Namespace declarations
- Docblock comments
- Any combination of the above
This significantly improves the rule's usability in real-world scenarios where certain types of long lines are acceptable or even preferred for code clarity.
This release represents a major enhancement to the Max Line Length Rule while maintaining 100% backward compatibility with existing configurations. We recommend gradually adopting the new array-based API for better flexibility and future-proofing your configuration.
Full Changelog: 1.5.1...1.6.0
Fixed Max Line Length Rule - Use Statement Ignoring
Release Notes - Version 1.5.1
🐛 Bug Fixes
🔧 Fixed Max Line Length Rule - Use Statement Ignoring
Bug Fix: Use Statement Ignoring Not Working Correctly
-
Class:
Phauthentic\PHPStanRules\CleanCode\MaxLineLengthRule -
Issue: When
ignoreUseStatementswas set totrue, the rule was not properly ignoring long use statement lines. The check only examined the node type during initial processing, but didn't account for cases where the same line could be processed multiple times or where use statements appeared on lines that exceeded the maximum length. -
Solution:
- Implemented a caching mechanism to track which lines contain use statements per file
- Added proper line-level checking to ensure use statements are consistently ignored regardless of processing order
- Enhanced the rule to check both the node type and the cached line information
-
Impact:
- Use statements that exceed the maximum line length are now correctly ignored when
ignoreUseStatements: trueis configured - Other long lines in the same file continue to be detected as expected
- No breaking changes - existing configurations continue to work as intended
- Use statements that exceed the maximum line length are now correctly ignored when
-
Testing:
- Added comprehensive test cases to verify use statements are properly ignored
- Added test cases to ensure non-use statement lines are still detected when use statements are ignored
- Ensures the fix doesn't break the default behavior of detecting long use statements
💡 Why This Matters
Previously, developers who configured the rule to ignore use statements might have still received false positives for long use statement lines. This fix ensures that when you configure the rule to ignore use statements, those lines are consistently and reliably ignored, allowing you to focus on enforcing line length limits for actual code logic rather than import statements.
Before (1.5.0): Long use statements could still trigger errors even when ignoreUseStatements: true
After (1.5.1): Long use statements are properly ignored when configured, while other long lines are still detected
This is a bug fix release that improves the reliability of the Max Line Length Rule's use statement ignoring feature. All existing configurations continue to work without any changes required.
Full Changelog: 1.5.0...1.5.1
1.5.0
Release Notes - Version 1.5.0
🎉 New Features
✨ Enhanced Dependency Constraints Rule
Enhancement: FQCN (Fully Qualified Class Name) Checking
-
Class:
Phauthentic\PHPStanRules\Architecture\DependencyConstraintsRule -
Purpose: Extended to check not only
usestatements but also fully qualified class names throughout your codebase -
Key Features:
- Backward Compatible: Existing configurations continue to work unchanged (FQCN checking is opt-in)
- Comprehensive Coverage: Detects forbidden dependencies in 11 different contexts
- Selective Checking: Configure which reference types to check for optimal performance
- Flexible Configuration: Enable FQCN checking with a simple boolean flag
-
Supported Reference Types:
new- Class instantiations (e.g.,new \DateTime())param- Parameter type hints (e.g.,function foo(\DateTime $date))return- Return type hints (e.g.,function foo(): \DateTime)property- Property type hints (e.g.,private \DateTime $date)static_call- Static method calls (e.g.,\DateTime::createFromFormat())static_property- Static property access (e.g.,\DateTime::ATOM)class_const- Class constant (e.g.,\DateTime::class)instanceof- instanceof checks (e.g.,$x instanceof \DateTime)catch- catch blocks (e.g.,catch (\Exception $e))extends- class inheritance (e.g.,class Foo extends \DateTime)implements- interface implementation (e.g.,class Foo implements \DateTimeInterface)
-
Configuration: Supports new optional parameters:
checkFqcn(boolean, default:false) - Enable FQCN checkingfqcnReferenceTypes(array, default: all types) - Select specific reference types to check
📚 Documentation Improvements
📚 Enhanced Dependency Constraints Rule Documentation
- Comprehensive Examples: Added detailed configuration examples for basic usage, FQCN checking, and selective reference types
- Use Cases Section: Added real-world examples including:
- Preventing
DateTimeusage in domain layers - Selective checking for performance optimization
- Preventing
- Reference Types Documentation: Complete list and explanation of all 11 supported reference types
- Backward Compatibility Notes: Clear explanation of how existing configurations are unaffected
📚 README Improvements
- New Section: "What if I need to ignore a Rule in a certain Place?"
- Explains how to use PHPStan inline annotations
- Emphasizes keeping rule exceptions documented close to the code
- Encourages adding comments explaining why a rule is broken
🚀 Migration Guide
For Existing Users
No Action Required! All existing configurations continue to work without any changes. The new FQCN checking feature is disabled by default (checkFqcn: false), so your current setup will behave exactly as before.
💡 Why This Matters
The previous version only checked use statements, which meant developers could bypass dependency constraints by using fully qualified class names. This release closes that loophole while maintaining backward compatibility.
Before (1.4.0): Only use DateTime; would be caught
After (1.5.0): All of these are now caught when checkFqcn: true:
use DateTime;new \DateTime()function process(\DateTime $date)function get(): \DateTimeprivate \DateTime $createdAt- And 6 more reference types!
This significantly strengthens your architecture enforcement capabilities and helps maintain clean boundaries between layers and modules.
This release represents a major enhancement to the Dependency Constraints Rule while maintaining 100% backward compatibility with existing configurations. We recommend gradually enabling FQCN checking in your projects to ensure complete dependency constraint enforcement.
Full Changelog: 1.4.0...1.5.0
1.4.0
🎉 New Features
✨ Modular Architecture Rules
New Rule: Modular Architecture Rule
- Class:
Phauthentic\PHPStanRules\Architecture\ModularArchitectureRule - Purpose: Enforces strict dependency rules for modular hexagonal (Ports and Adapters) architecture with capabilities/modules
- Key Features:
- Enforces intra-module layer dependencies (Domain, Application, Infrastructure, Presentation)
- Enforces cross-module dependencies using configurable regex patterns
- Supports custom layer dependency rules
- Configurable base namespace for capabilities/modules
- Configuration: Supports
baseNamespace,layerDependencies, andallowedCrossModulePatternsparameters - Example: Perfect for modular monoliths where each capability/module follows a layered architecture pattern
New Rule: Circular Module Dependency Rule
- Class:
Phauthentic\PHPStanRules\Architecture\CircularModuleDependencyRule - Purpose: Detects circular dependencies between modules in a modular architecture
- Key Features:
- Tracks module-to-module dependencies
- Reports circular dependency chains (e.g., Module A → Module B → Module C → Module A)
- Configurable base namespace for capabilities/modules
- Configuration: Requires
baseNamespaceparameter
✨ Specification Docblock Rule
New Rule: Class Must Have Specification Docblock Rule
- Class:
Phauthentic\PHPStanRules\Architecture\ClassMustHaveSpecificationDocblockRule - Purpose: Ensures that classes, interfaces, and/or methods matching specified patterns have a properly formatted docblock with a "Specification:" section
- Key Features:
- Validates classes and interfaces using regex patterns
- Validates methods using
FQCN::methodNameformat with regex patterns - Configurable specification header text (default: "Specification:")
- Optional requirement for blank line after header
- Optional requirement for list items to end with periods
- Supports annotations after specification section
- Configuration: Supports
classPatterns,methodPatterns,specificationHeader,requireBlankLineAfterHeader, andrequireListItemsEndWithPeriodparameters
✨ Enhanced Clean Code Rules
Too Many Arguments Rule - Pattern Support
- Enhancement: Added optional
patternsparameter to apply rule only to classes matching specific regex patterns - Backward Compatible: Existing configurations without
patternscontinue to work (applies to all classes) - Example: Can now configure to only check specific classes like
'/.*Service$/'or'/App\\Service\\/'
Max Line Length Rule - Use Statement Ignoring
- Enhancement: Added
ignoreUseStatementsparameter to optionally ignore use statement lines - Configuration: Boolean flag (default:
false) to exclude use statements from line length checking
📚 Documentation Improvements
📚 New Documentation Files
- Modular Architecture Rule: Complete documentation with examples for modular monolith architectures
- Circular Module Dependency Rule: Full documentation with configuration examples
- Class Must Have Specification Docblock Rule: Comprehensive documentation with multiple configuration examples for classes, interfaces, and methods
- Too Many Arguments Rule: Updated documentation with pattern support examples
- Max Line Length Rule: Updated documentation with
ignoreUseStatementsparameter
📚 Documentation Structure Improvements
- Refactored Documentation: Moved all individual rule documentation from
docs/Rules.mdto individual files indocs/rules/directory - Improved Navigation: Each rule now has its own dedicated documentation file for better discoverability
- Enhanced Examples: Added comprehensive configuration examples for all new rules
- Real-world Use Cases: Added practical examples for modular architecture setup
🚀 Migration Guide
For Existing Users
All existing configurations continue to work without changes. The new rules are opt-in and require explicit configuration.
For New Modular Architecture Features
To use the new modular architecture rules:
services:
-
class: Phauthentic\PHPStanRules\Architecture\ModularArchitectureRule
arguments:
baseNamespace: 'App\\Capability'
layerDependencies:
Domain: []
Application: [Domain]
Infrastructure: [Domain, Application]
Presentation: [Application]
allowedCrossModulePatterns:
- '/Facade$/'
- '/FacadeInterface$/'
- '/Input$/'
- '/Result$/'
tags:
- phpstan.rules.rule
-
class: Phauthentic\PHPStanRules\Architecture\CircularModuleDependencyRule
arguments:
baseNamespace: 'App\\Capability'
tags:
- phpstan.rules.ruleFor Specification Docblock Validation
To enforce specification docblocks:
services:
-
class: Phauthentic\PHPStanRules\Architecture\ClassMustHaveSpecificationDocblockRule
arguments:
classPatterns:
- '/.*Facade$/'
- '/.*Command$/'
methodPatterns:
- '/.*Repository::find.*/'
specificationHeader: 'Specification:'
requireBlankLineAfterHeader: true
requireListItemsEndWithPeriod: false
tags:
- phpstan.rules.ruleFor Enhanced Clean Code Rules
To use pattern matching with Too Many Arguments Rule:
services:
-
class: Phauthentic\PHPStanRules\CleanCode\TooManyArgumentsRule
arguments:
maxArguments: 3
patterns: ['/.*Service$/', '/App\\Controller\\/']
tags:
- phpstan.rules.ruleTo ignore use statements in Max Line Length Rule:
services:
-
class: Phauthentic\PHPStanRules\CleanCode\MaxLineLengthRule
arguments:
maxLineLength: 80
ignoreUseStatements: true
tags:
- phpstan.rules.ruleThis release significantly expands the capabilities of phpstan-rules, especially for teams working with modular monolith architectures and clean code practices, while maintaining full backward compatibility with existing configurations.
1.2.1
Release Notes
🐛 Bug Fixes
Final Class Rule
- Fixed: Abstract classes are now properly ignored by default to prevent false positives
- Added: Configurable
ignoreAbstractClassesparameter (default:true) for users who want to enforce final declaration on abstract classes
Configuration
-
class: Phauthentic\PHPStanRules\Architecture\ClassMustBeFinalRule
arguments:
patterns: ['/^App\\Service\\/']
ignoreAbstractClasses: true # Default behavior
tags:
- phpstan.rules.ruleBackward Compatible: All existing configurations continue to work without changes.
1.2.0: Improving the MethodMustReturnType to support unions (#7)
Release Notes
🎉 New Features
✨ Enhanced Method Must Return Type Rule
- New Feature: Added support for "void" as a type in addition to the legacy
void: trueapproach - New Feature: Added
oneOffunctionality for union types - allows specifying an array of types where one must match - New Feature: Added
allOffunctionality for union types - allows specifying an array of types where all must be present - New Feature: Added
anyOfas an alias foroneOffor better readability - New Feature: Added regex pattern support in
oneOf,allOf, andanyOfarrays usingregex:prefix - Enhancement: Made configuration fields optional with sensible defaults (
nullable,void,objectTypePattern) - Enhancement: Added configuration normalization to handle missing fields gracefully
🔧 Configuration Improvements
- Backward Compatibility: All existing configurations continue to work without changes
- Flexible Configuration: Minimal configurations now work without requiring all fields
- Regex Support: Can use patterns like
'regex:/^App\\Entity\\/'to match entity classes
🔧 Documentation Improvements
📚 Enhanced Method Must Return Type Rule Documentation
- New Examples: Added comprehensive examples for
oneOf,allOf, andanyOfusage - Regex Documentation: Added documentation for regex pattern support with examples
- Configuration Guide: Updated configuration examples to show new optional fields
- Usage Examples: Added real-world examples for entity validation and union types
📚 Updated Configuration Examples
- New Configuration Patterns: Added examples for minimal configurations
- Regex Examples: Added examples showing how to use regex patterns for class matching
- Union Type Examples: Added examples for both
oneOfandallOfscenarios
✅ New Test Cases
�� Comprehensive Test Coverage
- AnyOfRuleTest: Tests for the new
anyOffunctionality - RegexRuleTest: Tests for regex pattern matching in
anyOfarrays - RegexAllOfRuleTest: Tests for regex pattern matching in
allOfarrays - EntityRegexRuleTest: Tests for realistic entity pattern matching scenarios
- FacadeRuleTest: Tests for minimal configuration scenarios
- UnionTypeRuleTest: Tests for union type functionality
- Enhanced MethodMustReturnTypeRuleTest: Updated existing tests for new functionality
📁 New Test Data Files
data/MethodMustReturnType/AnyOfTestClass.php: Test cases foranyOffunctionalitydata/MethodMustReturnType/EntityRegexTestClass.php: Test cases for entity regex patternsdata/MethodMustReturnType/FacadeTestClass.php: Test cases for minimal configurationsdata/MethodMustReturnType/RegexAllOfTestClass.php: Test cases forallOfwith regexdata/MethodMustReturnType/RegexTestClass.php: Test cases for basic regex functionalitydata/MethodMustReturnType/UnionTypeTestClass.php: Test cases for union type validation
🏗️ Code Quality Improvements
🔧 Enhanced MethodMustReturnTypeRule
- New Methods: Added
normalizeConfig(),isTypeMatchWithRegex(),getExpectedTypeDescription() - Improved Error Handling: Better error messages for union types and regex patterns
- Code Organization: Better separation of concerns with dedicated methods for different validation types
- Type Safety: Enhanced type checking and validation logic
🐛 Bug Fixes
- Configuration Defaults: Fixed issues with missing configuration fields causing errors
- Regex Pattern Handling: Proper boolean conversion for regex pattern matching
- Union Type Parsing: Improved union type parsing and validation logic
- Error Message Consistency: Standardized error message formatting
📊 Statistics
- 16 files changed with 700+ lines added and 33 lines removed
- 17 new test files created for comprehensive coverage
- 100% backward compatibility maintained with existing configurations
🚀 Migration Guide
For Existing Users
No changes required! All existing configurations will continue to work exactly as before.
For New Features
To use the new union type functionality:
-
class: Phauthentic\PHPStanRules\Architecture\MethodMustReturnTypeRule
arguments:
returnTypePatterns:
-
pattern: '/^MyClass::getValue$/'
anyOf: ['int', 'string', 'bool']
-
pattern: '/^MyClass::getEntity$/'
anyOf: ['regex:/^App\\Entity\\/', 'void']
tags:
- phpstan.rules.ruleThis release significantly enhances the flexibility and power of the Method Must Return Type Rule while maintaining full backward compatibility.
1.1.0
Release Notes
🎉 New Features
✨ New Rule: Catch Exception of Type Not Allowed Rule
- Class:
Phauthentic\PHPStanRules\Architecture\CatchExceptionOfTypeNotAllowedRule - Purpose: Prevents catching overly broad exception types like
Exception,Error, orThrowable - Configuration: Accepts an array of forbidden exception types
- Example: Configure to prevent catching
Exception,Error, orThrowablefor better error handling practices
✨ Enhanced Method Signature Must Match Rule
- New Feature: Added visibility scope validation
- New Feature: Improved parameter validation with optional type checking
- Enhancement: Better error messages and validation logic
- Configuration: Now supports
visibilityScopeparameter (public, protected, private)
🔧 Documentation Improvements
📚 Fixed Class Name References
Updated all configuration examples to use correct class names:
ReadonlyClassRule→ClassMustBeReadonlyRuleFinalClassRule→ClassMustBeFinalRuleNamespaceClassPatternRule→ClassnameMustMatchPatternRule
📚 Added Missing Rule Documentation
- Methods Returning Bool Must Follow Naming Convention Rule: Complete documentation added with configuration examples
- Catch Exception of Type Not Allowed Rule: Full documentation with examples
📚 Enhanced Documentation Structure
- Added anchor links to all rule sections for better navigation
- Improved README.md with clearer examples
- Updated namespace references from
Phauthentic\PhpstanRulestoPhauthentic\PHPStanRules
✅ New Test Cases
- CatchExceptionOfTypeNotAllowedRuleTest: Comprehensive tests for the new exception catching rule
- Enhanced MethodSignatureMustMatchRuleTest: Additional test cases for visibility scope and parameter validation
📁 New Test Data Files
data/CatchExceptionOfTypeNotAllowed/CatchAllowedException.php: Examples of allowed exception catchingdata/CatchExceptionOfTypeNotAllowed/CatchForbiddenException.php: Examples of forbidden exception catching- Enhanced
data/MethodSignatureMustMatch/TestClass.php: Additional test methods for validation
🏗️ Code Quality Improvements
🔧 Refactoring
- MethodSignatureMustMatchRule: Improved code structure with better separation of concerns
- MethodMustReturnTypeRule: Enhanced documentation and code comments
- phpstan.neon: Removed hardcoded rule configurations (now serves as a clean template)
🐛 Bug Fixes
- Fixed namespace casing inconsistencies (
PhpstanRules→PHPStanRules) - Improved parameter validation logic in MethodSignatureMustMatchRule
- Enhanced error message formatting and consistency