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 Doctrine Laravel Package

phpstan/phpstan-doctrine

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev phpstan/phpstan-doctrine
    

    Use phpstan/extension-installer for automatic configuration, or manually include:

    includes:
        - vendor/phpstan/phpstan-doctrine/extension.neon
    
  2. First Use Case: Run PHPStan on a Doctrine-heavy project:

    vendor/bin/phpstan analyse src
    

    The extension will immediately validate:

    • Entity repository method calls (findBy*, findOneBy*, countBy*).
    • Basic DQL syntax (if objectManagerLoader is configured).

Implementation Patterns

Core Workflows

  1. Repository Method Validation:

    // Validated automatically
    $user = $userRepository->findOneBy(['email' => 'test@example.com']);
    

    PHPStan will infer $user as ?User (nullable) and validate field names (email).

  2. QueryBuilder/DQL Type Inference:

    $query = $entityManager->createQuery('SELECT u FROM App\Entity\User u');
    $users = $query->getResult(); // array<User>
    

    Requires objectManagerLoader in phpstan.neon:

    parameters:
        doctrine:
            objectManagerLoader: tests/bootstrap.php
    
  3. Custom Repository Base Class:

    parameters:
        doctrine:
            ormRepositoryClass: App\Repository\CustomRepository
    

    Extends validation to custom repository methods.

  4. Dead Code Detection: Disable false positives for Doctrine-managed fields:

    #[ORM\GeneratedValue]
    private ?int $id = null; // Won't trigger "unused property" warnings
    

Integration Tips

  • Symfony Projects: Use the provided Symfony 4/5 objectManagerLoader examples.
  • Gedmo Extensions: Enable dead-code detection for Gedmo fields (e.g., Timestampable).
  • Dynamic QueryBuilders: Avoid passing QueryBuilders to methods to enable static analysis.
  • Collection Methods: Narrow Collection::first() return types when isEmpty() is checked:
    if (!$collection->isEmpty()) {
        $item = $collection->first(); // User (not User|false)
    }
    

Gotchas and Tips

Pitfalls

  1. DQL Validation Limitations:

    • Subqueries return mixed (not statically analyzable).
    • Dynamic expressions (e.g., ->select($dynamicField)) break type inference.
    • Enable reporting with:
      parameters:
          doctrine:
              reportDynamicQueryBuilders: true
      
  2. Custom Types:

    • Missing descriptors for custom Doctrine types cause failures. Enable reporting:
      parameters:
          doctrine:
              reportUnknownTypes: true
      
    • Use ReflectionDescriptor for types with proper typehints:
      services:
          - factory: PHPStan\Type\Doctrine\Descriptors\ReflectionDescriptor('App\Type\CustomType')
            tags: [phpstan.doctrine.typeDescriptor]
      
  3. Literal Strings:

    • Enforce literal-string for SQL parameters to prevent SQL injection:
      parameters:
          doctrine:
              literalString: true
      
    • Avoid dynamic strings in Connection::executeQuery():
      // ❌ Risky
      $sql = "SELECT * FROM users WHERE email = '$userInput'";
      
      // ✅ Safe
      $sql = "SELECT * FROM users WHERE email = ?";
      
  4. Proxy Classes:

    • Direct use of Doctrine proxy class names (e.g., Proxy\__CG__\App\Entity\User) triggers warnings. Use interfaces or base classes instead.
  5. Final Classes/Constructors:

    • final entity classes/constructors may break proxy generation. Configure allowed cases:
      parameters:
          doctrine:
              allowFinalEntityClasses: true
              allowFinalConstructors: true
      

Debugging Tips

  • Type Inference Issues: Check objectManagerLoader returns a valid EntityManager.
  • Custom DQL Functions: Implement TypedExpression for accurate type inference.
  • Performance: Exclude slow analyses (e.g., DQL validation) in CI:
    levels:
        - 5
    parameters:
        doctrine:
            objectManagerLoader: null # Disable in CI
    

Extension Points

  1. Custom Rules: Extend DoctrineExtension to add project-specific validations.
  2. Stub Files: Override stubs in vendor/phpstan/phpstan-doctrine/stubs/ for legacy Doctrine versions.
  3. Configuration: Use parameters.doctrine to tweak behavior (e.g., allCollectionsSelectable for Collection::matching()).

```markdown
## Example Debugging Workflow
1. **Error**: `Call to undefined method App\Entity\UserRepository::customMethod()`.
   - **Fix**: Add `ormRepositoryClass` to `phpstan.neon` pointing to the base class with `customMethod`.

2. **Error**: `Type error: Return type of App\Type\CustomType::convertToPHPValue() must be string|int, mixed given`.
   - **Fix**: Implement a `DoctrineTypeDescriptor` or use `ReflectionDescriptor`.

3. **False Positive**: `Unused property $createdAt` (Gedmo field).
   - **Fix**: Ensure `phpstan-doctrine` is included **after** `phpstan/extension-installer` in `includes`.
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.
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager