Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpstan Extensions Laravel Package

slam/phpstan-extensions

PHPStan extensions with extra strict rules: unused variables, closure parameter typehints, enforce ::class notation, forbid goto, naming conventions, validate PHPUnit annotation FQCNs, and restrict access to globals/static properties in specific contexts.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev slam/phpstan-extensions
    

    For automatic inclusion with phpstan/extension-installer, no further steps are needed.

  2. Manual Inclusion (if not using extension-installer): Add to your phpstan.neon:

    includes:
        - vendor/slam/phpstan-extensions/conf/slam-rules.neon
    
  3. First Use Case: Run PHPStan with the default config:

    vendor/bin/phpstan analyse src
    

    Focus on UnusedVariableRule and StringToClassRule for immediate feedback—these catch common refactoring opportunities.


Implementation Patterns

Core Workflows

  1. Enforcing Naming Conventions: Use ClassNotationRule to standardize class naming (e.g., Abstract prefix for abstract classes, Interface suffix for interfaces).

    # phpstan.neon
    includes:
        - vendor/slam/phpstan-extensions/conf/slam-rules.neon
    rules:
        SlamPhpStan\ClassNotationRule:
            enabled: true
    
  2. Dependency Injection for Time: Replace raw DateTime calls with abstractions (e.g., lcobucci/clock) using not-now-rules.neon:

    includes:
        - vendor/slam/phpstan-extensions/conf/not-now-rules.neon
    

    Pattern: Wrap DateTime logic in a service with a clock dependency:

    class OrderService {
        public function __construct(private Clock $clock) {}
        public function getCurrentOrderDate(): DateTimeImmutable {
            return $this->clock->now();
        }
    }
    
  3. Symfony-Specific Rules: Enforce Symfony’s filesystem/process components over raw PHP functions:

    includes:
        - vendor/slam/phpstan-extensions/conf/symfony-rules.neon
    

    Pattern: Replace file_exists() with Symfony\Component\Filesystem\Filesystem::exists().

  4. PHPUnit Annotations: Validate @expectedException, @covers, etc., with PhpUnitFqcnAnnotationRule:

    /**
     * @expectedException \RuntimeException
     */
    public function testException(): void {}
    

    Pattern: Ensure exception classes exist and are fully qualified.

  5. Singleton Prohibition: Block $_GET, $_POST, or Yii::$app in models using AccessGlobalVariableWithinContextRule:

    rules:
        SlamPhpStan\AccessGlobalVariableWithinContextRule:
            forbiddenGlobals: ['$_GET', '$_POST']
            forbiddenClasses: ['yii\db\ActiveRecordInterface']
    

Integration Tips

  • Layered Configuration: Combine configs for different frameworks (e.g., Symfony + Yii) by including multiple .neon files:

    includes:
        - vendor/slam/phpstan-extensions/conf/slam-rules.neon
        - vendor/slam/phpstan-extensions/conf/symfony-rules.neon
        - vendor/slam/phpstan-extensions/conf/yii-rules.neon
    
  • CI/CD Pipeline: Add PHPStan with Slam extensions to your CI (e.g., GitHub Actions):

    - name: Run PHPStan
      run: vendor/bin/phpstan analyse --level=max src --configuration=phpstan.neon
    
  • Gradual Adoption: Start with StringToClassRule and UnusedVariableRule (low effort, high impact). Enable stricter rules (e.g., MissingClosureParameterTypehintRule) in phases.


Gotchas and Tips

Pitfalls

  1. UnusedVariableRule False Positives:

    • Issue: Variables used in compact(), array_merge(), or dynamic function calls may be flagged incorrectly.
    • Fix: Update your PHPStan version (v6.3.0+ handles compact() better) or suppress false positives:
      rules:
          SlamPhpStan\UnusedVariableRule:
              ignoreVariables: ['_temp']
      
  2. MissingClosureParameterTypehintRule Strictness:

    • Issue: Rejects all closures without type hints, including those in legacy code or third-party libraries.
    • Fix: Disable for specific files or namespaces:
      rules:
          SlamPhpStan\MissingClosureParameterTypehintRule:
              paths:
                  - '!vendor/**'
                  - '!legacy/**'
      
  3. not-now-rules.neon Limitations:

    • Issue: Rules for strtotime() or date() may miss edge cases (e.g., dynamic strings).
    • Fix: Use a custom rule or suppress with:
      rules:
          SlamPhpStan\NoTimeRule:
              ignoreFunctions: ['my_custom_date_function']
      
  4. Symfony/Yii Rules Overhead:

    • Issue: Rules like SymfonyFilesystemRule may break legacy code relying on raw PHP functions.
    • Fix: Exclude directories or use ignoreNodes:
      rules:
          SlamPhpStan\SymfonyFilesystemRule:
              ignoreNodes:
                  - 'Symfony\Component\Filesystem\Filesystem::isReadable' # if needed
      

Debugging Tips

  • Error Identifiers: Use the --error-format=github flag to see rule-specific identifiers (added in v6.4.0):

    vendor/bin/phpstan analyse --error-format=github src
    

    Example output:

    ❌ [SlamPhpStan\StringToClassRule] Class string 'App\Models\User' should use ::class notation.
    
  • Rule-Specific Configuration: Override defaults per rule. Example for ClassNotationRule:

    rules:
        SlamPhpStan\ClassNotationRule:
            interfaceSuffix: 'I' # Customize suffix
            abstractPrefix: 'Base' # Customize prefix
    
  • Performance: Exclude tests or large directories from strict rules to speed up analysis:

    parameters:
        excludeFiles:
            - 'tests/**'
            - 'vendor/**'
    

Extension Points

  1. Custom Rules: Extend existing rules by subclassing SlamPhpStan\Rule\Rule and overriding refineNodes() or processNode().

  2. Dynamic Config: Use PHPStan’s parameters to dynamically enable/disable rules based on environment variables:

    parameters:
        strictMode: '%env(bool:STRICT_MODE,false)%'
    rules:
        SlamPhpStan\MissingClosureParameterTypehintRule:
            enabled: '%parameters.strictMode%'
    
  3. Community Contributions:

    • Report false positives/edge cases to the GitHub repo.
    • Contribute new rules (e.g., for Laravel’s Facade pattern or custom abstractions).

Pro Tips

  • Pair with phpstan/extension-installer: Automatically load extensions without manual includes:

    composer require --dev phpstan/extension-installer
    

    Add to composer.json:

    "extra": {
        "installer-paths": {
            "config/phpstan/extensions": ["slam/phpstan-extensions"]
        }
    }
    
  • Visual Studio Code Integration: Use the PHPStan extension for real-time feedback:

    // .vscode/settings.json
    {
        "phpstan.executablePath": "vendor/bin/phpstan",
        "phpstan.neonPath": "phpstan.neon"
    }
    
  • Legacy Code Migration: Use not-now-rules.neon incrementally. Start by suppressing rules for specific files, then refactor:

    rules:
        SlamPhpStan\NoTimeRule:
            ignoreFiles: ['legacy/DateHelper.php']
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky