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

Psalm Plugin Laravel Package

php-standard-library/psalm-plugin

Psalm plugin for PHP Standard Library (PSL) that improves type inference for PSL Type specifications (e.g., shape/optional), producing more precise array shapes and safer analysis. Install via Composer and enable with psalm-plugin.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Plugin:
    composer require --dev php-standard-library/psalm-plugin
    
  2. Enable the Plugin:
    vendor/bin/psalm-plugin enable php-standard-library/psalm-plugin
    
  3. Verify Integration: Run Psalm with the plugin enabled:
    vendor/bin/psalm --init
    vendor/bin/psalm
    

First Use Case: PSL Type Coercion

Use the plugin to enforce precise type hints for PSL-coerced data. For example:

use Psl\Type;

$spec = Type\shape([
    'name' => Type\string(),
    'age' => Type\int(),
]);

$data = $spec->coerce($_GET['user']);
// Without plugin: Psalm infers `array<string|int, mixed>`
// With plugin: Psalm infers `array{name: string, age: int}`

Where to Look First

  • Plugin Documentation: GitHub Repository
  • Psalm Configuration: Ensure psalm-plugin is enabled in psalm.config.php:
    <?php
    return [
        'plugins' => [
            'Psl\Psalm\Plugin',
        ],
    ];
    
  • PSL Documentation: PHP Standard Library for type definitions.

Implementation Patterns

Workflow: Integrating PSL with Psalm

  1. Define PSL Shapes: Use PSL’s Type namespace to define strict data contracts:

    use Psl\Type;
    
    $userShape = Type\shape([
        'id' => Type\positive_int(),
        'email' => Type\email_address(),
        'roles' => Type\list_of(Type\string()),
    ]);
    
  2. Coerce and Validate: Apply shapes to runtime data and let Psalm infer precise types:

    $userData = $userShape->coerce($_POST['user']);
    // Psalm now knows `$userData` is `array{id: positive-int, email: email-address, roles: list<string>}`
    
  3. Leverage IDE Features: Psalm’s type inference enables autocompletion and error detection in IDEs (e.g., PHPStorm, VSCode).


Integration Tips

  • Laravel-Specific: Use PSL shapes in Form Request validation or API resource contracts:

    // app/Http/Requests/StoreUserRequest.php
    public function rules(): array
    {
        return [
            'user' => ['required', new PSLTypeRule($this->userShape)],
        ];
    }
    

    Note: Create a custom PSLTypeRule to bridge PSL shapes with Laravel’s validation.

  • CI/CD Pipeline: Add Psalm to your CI checks (e.g., GitHub Actions):

    - name: Run Psalm with PSL Plugin
      run: vendor/bin/psalm --init --no-cache
    
  • Testing: Use PSL shapes in PHPUnit tests to enforce type safety:

    public function testUserShape(): void
    {
        $shape = Type\shape(['name' => Type\string()]);
        $data = $shape->coerce(['name' => 'John']);
        self::assertIsArray($data);
        self::assertArrayHasKey('name', $data);
    }
    
  • Migration Strategy: Gradually replace runtime validation (e.g., Validator::make()) with PSL shapes where Psalm can statically verify correctness.


Gotchas and Tips

Pitfalls

  1. Plugin Compatibility:

    • Ensure your Psalm version matches the plugin’s compatibility table (e.g., psalm-plugin@^2.1 for Psalm 5).
    • Fix: Downgrade Psalm or update the plugin:
      composer require php-standard-library/psalm-plugin@2.0.0
      
  2. Type Inference Limits:

    • Psalm may still infer loose types for dynamic PSL operations (e.g., Type\any()).
    • Workaround: Use @psalm-suppress or refine shapes:
      /** @psalm-suppress MixedAssignment */
      $data = Type\any()->coerce($input);
      
  3. Performance Overhead:

    • Running Psalm with the plugin can slow down analysis for large codebases.
    • Tip: Exclude non-critical paths in psalm.config.php:
      return [
          'exclude_paths' => ['tests', 'vendor'],
      ];
      
  4. IDE Sync Issues:

    • Some IDEs (e.g., PHPStorm) may not reflect Psalm’s type improvements immediately.
    • Fix: Restart the IDE or trigger a full Psalm analysis.

Debugging Tips

  1. Enable Verbose Output: Run Psalm with --verbose to diagnose plugin issues:

    vendor/bin/psalm --verbose
    
  2. Check Plugin Status: Verify the plugin is enabled:

    vendor/bin/psalm-plugin list
    
  3. Isolate Problems: Test the plugin on a single file to isolate issues:

    vendor/bin/psalm --init --no-cache path/to/file.php
    

Extension Points

  1. Custom Return Type Providers: Extend the plugin by adding new return type providers for unsupported PSL functions. Example:

    use Psalm\Plugin\ReturnTypeProviderInterface;
    
    class CustomPslProvider implements ReturnTypeProviderInterface
    {
        public function getProvidedReturnType(): string
        {
            return 'array{...}';
        }
    
        public function getFunction(): string
        {
            return 'Psl\\Some\\Function';
        }
    }
    

    Register it in psalm.config.php:

    return [
        'plugins' => [
            'Psl\Psalm\Plugin',
            'CustomPslProvider',
        ],
    ];
    
  2. Psalm Configuration Overrides: Override default plugin behavior via psalm.config.php:

    return [
        'plugins' => [
            'Psl\Psalm\Plugin' => [
                'strict_mode' => true,
            ],
        ],
    ];
    
  3. Community Contributions:


Laravel-Specific Quirks

  1. Service Container Conflicts: PSL shapes may clash with Laravel’s type hints (e.g., array vs. array{...}). Solution: Use @psalm-type annotations for Laravel-specific types:

    /** @psalm-type UserArray array{id: int, name: string} */
    
  2. Eloquent Model Casting: Combine PSL with Eloquent’s $casts to enforce type safety:

    use Psl\Type;
    
    protected $casts = [
        'email' => 'string',
        'active' => 'bool',
    ];
    
    // In a PSL shape:
    $userShape = Type\shape([
        'email' => Type\email_address(),
        'active' => Type\bool(),
    ]);
    
  3. Request Validation: Use PSL shapes in API resources to enforce type contracts:

    // app/Http/Resources/UserResource.php
    public function toArray($request)
    {
        $shape = Type\shape(['id' => Type\int()]);
        $data = $shape->coerce($this->resource);
        return $data;
    }
    
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
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