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 Safe Rule Laravel Package

thecodingmachine/phpstan-safe-rule

PHPStan rule set that flags calls to “unsafe” PHP functions that can return false on failure and suggests using the thecodingmachine/safe equivalents that throw exceptions, helping enforce safer, exception-based error handling in your codebase.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Installation:

    composer require --dev thecodingmachine/phpstan-safe-rule thecodingmachine/safe
    

    Ensure thecodingmachine/safe is installed as a dependency (not just dev-dependency) since it provides the safe alternatives.

  2. Enable the Rule: Add the extension to your phpstan.neon:

    includes:
        - vendor/thecodingmachine/phpstan-safe-rule/extension.neon
    
  3. First Use Case: Run PHPStan on your codebase:

    vendor/bin/phpstan analyse src
    

    The rule will flag unsafe function calls (e.g., file_get_contents() without null checks) and suggest using Safe\file_get_contents() instead.

  4. Quick Check: Test with a known unsafe call:

    $content = file_get_contents('nonexistent.txt'); // Will trigger a warning
    

    PHPStan will suggest replacing it with:

    use Safe\file_get_contents;
    $content = file_get_contents('nonexistent.txt'); // Now throws on failure
    

Implementation Patterns

1. CI/CD Integration

  • GitHub Actions Example:

    - name: Run PHPStan Safe Rule
      run: vendor/bin/phpstan analyse --level=5 --error-format=github
    

    Fail the build if unsafe calls are detected.

  • Parallel Execution: Split analysis by directory in CI to reduce runtime:

    vendor/bin/phpstan analyse src/Modules --memory-limit=1G
    

2. Progressive Enforcement

  • Start Loose, Tighten Later: Begin with --level=1 (basic checks) and incrementally raise to --level=5 (strict).

    # phpstan.neon
    parameters:
        level: 1
    
  • Ignore Legacy Code:

    ignoreErrors:
        - '#.*legacy/.*#'
    

3. Safe Wrapper Adoption

  • Batch Replacement: Use sed or IDE refactoring (e.g., PHPStorm "Replace with Safe") to swap unsafe calls:

    # Example: Replace file_get_contents with Safe\file_get_contents
    find src -type f -name "*.php" -exec sed -i 's/file_get_contents/Safe\\file_get_contents/g' {} +
    
  • Alias for Convenience: Create a SafeFunctions.php trait to reduce verbosity:

    trait SafeFunctions {
        protected function safeFileGetContents(string $path): string {
            return Safe\file_get_contents($path);
        }
    }
    

4. Custom Rule Extensions

  • Extend Existing Rules: Override or extend the SafeRule class to handle project-specific cases:
    // app/Rules/CustomSafeRule.php
    use PHPStan\Rules\Rule;
    use TheCodingMachine\SafeRule\SafeRule;
    
    class CustomSafeRule extends SafeRule {
        public function getNodeType(): string {
            return 'Php\Node\Expr\MethodCall';
        }
    
        protected function customCheck(callable $node): void {
            // Add logic for project-specific unsafe patterns
        }
    }
    
    Register in phpstan.neon:
    services:
        - TheCodingMachine\SafeRule\SafeRule
        - App\Rules\CustomSafeRule
    

5. Type Hinting for Safe Functions

  • Leverage PHPStan’s Type System: The rule automatically infers return types for safe functions (e.g., Safe\preg_match now correctly types $matches). Example:
    $matches = Safe\preg_match('/\d+/', $subject); // $matches is now typed as ?array<string>
    

Gotchas and Tips

1. Common Pitfalls

  • Missing thecodingmachine/safe: The rule will not work without thecodingmachine/safe installed as a runtime dependency (not just dev-dependency). Fix: Run composer require thecodingmachine/safe.

  • False Positives with JSON_THROW_ON_ERROR: The rule may flag json_encode()/json_decode() calls even with JSON_THROW_ON_ERROR. Workaround: Whitelist in phpstan.neon:

    ignoreErrors:
        - '#.*json_(encode|decode).*JSON_THROW_ON_ERROR.*#'
    
  • Reflection Overhead: The rule uses lazy reflection processing (since v1.4.3). If you encounter performance issues, ensure your PHPStan version supports this optimization.

2. Debugging

  • Inspect Rule Output: Use --error-format=json to debug false positives:

    vendor/bin/phpstan analyse --error-format=json > errors.json
    

    Parse the JSON to identify problematic files/methods.

  • Disable Specific Rules: Temporarily disable the rule for a file:

    // @phpstan-ignore-file
    
  • Check Loading Order: Ensure extension.neon is included after your base config to avoid rule conflicts:

    # Correct order
    extends: phpstan:level-5
    includes:
        - vendor/thecodingmachine/phpstan-safe-rule/extension.neon
    

3. Performance Tips

  • Run on Changed Files: Use --diff in CI to analyze only modified files:

    vendor/bin/phpstan analyse --diff
    
  • Memory Limits: Increase memory for large codebases:

    vendor/bin/phpstan analyse --memory-limit=2G
    

4. Extension Points

  • Custom Safe Functions: Add support for project-specific safe wrappers by extending the rule:

    // app/Rules/ProjectSafeRule.php
    use TheCodingMachine\SafeRule\SafeRule;
    
    class ProjectSafeRule extends SafeRule {
        protected function getUnsafeFunctions(): array {
            return array_merge(parent::getUnsafeFunctions(), [
                'my_project\unsafe_function' => 'my_project\Safe\safe_function',
            ]);
        }
    }
    
  • Override Error Messages: Customize suggestions in the rule’s createError() method:

    protected function createError(callable $node, string $message): Error {
        return new Error(
            $this->getNodeName($node),
            $message . ' Use `Safe\\' . $this->getSafeFunctionName($node) . '()` instead.'
        );
    }
    

5. Configuration Quirks

  • PHP Version Compatibility: Requires PHP 8.1+ (since v1.4.0). Ensure your environment matches.

  • PHPStan Version: Works with PHPStan 2.0+ (since v1.3.0). Downgrade if using an older version:

    composer require phpstan/phpstan:^1.0
    
  • Strict Mode Conflicts: If using phpstan-strict-rules, disable overlapping rules to avoid redundancy:

    parameters:
        rules:
            TheCodingMachine\SafeRule\SafeRule: true
            PhpStan\Rules\StrictRules\StrictFunctionCallRule: false
    

6. Pro Tips

  • Pair with roave/security-advisories: Combine with roave/security-advisories to catch unsafe functions and vulnerable dependencies:

    composer require --dev roave/security-advisories
    
  • Visual Studio Code Integration: Add to settings.json for real-time feedback:

    "phpstan.executablePath": "vendor/bin/phpstan",
    "phpstan.neon": "./phpstan.neon",
    "phpstan.triggerMode": "workspace"
    
  • Benchmark Safe vs. Unsafe: Measure performance impact of safe wrappers:

    $time = microtime(true);
    Safe\file_get_contents('large_file.txt');
    echo "Safe: " . (microtime(true) - $time) . "s";
    
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata