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

Doctrine Doctor Laravel Package

ahmed-bhs/doctrine-doctor

Doctrine Doctor is a runtime analysis tool for Doctrine ORM integrated into the Symfony Web Profiler. It detects real-world issues like N+1 queries, slow queries, missing indexes, hydration overhead, and injection risks, with actionable backtraces and suggestions.

View on GitHub
Deep Wiki
Context7

layout: default

Configuration Reference


1. Overview

Doctrine Doctor uses Symfony's configuration system. All configuration is placed in YAML files under config/packages/.

1.1 Configuration Locations

config/
├── packages/
│   ├── dev/
│   │   └── doctrine_doctor.yaml         # Development-specific
│   └── doctrine_doctor.yaml              # All environments

1.2 Configuration Precedence

Environment-specific (config/packages/dev/)
    ↓ overrides
Global (config/packages/)
    ↓ overrides
Bundle defaults (DependencyInjection/Configuration.php)

2. Configuration Structure

2.1 Complete Configuration Tree

doctrine_doctor:
    # Master switch
    enabled: true|false

    analysis:
        exclude_third_party_entities: true|false
        exclude_paths: ['vendor/', 'var/cache/']

    # Profiler integration settings
    profiler:
        show_in_toolbar: true|false
        show_debug_info: true|false

    debug:
        enabled: true|false
        internal_logging: true|false

    # Individual analyzer settings
    analyzers:
        analyzer_name:
            enabled: true|false
            # Analyzer-specific parameters
            threshold: <value>
            # ... additional parameters

2.2 Default Values

When no configuration file exists, Doctrine Doctor uses these defaults:

doctrine_doctor:
    enabled: true

    analysis:
        exclude_third_party_entities: true
        exclude_paths: ['vendor/']

    profiler:
        show_in_toolbar: true
        show_debug_info: false

    debug:
        enabled: false
        internal_logging: false

    analyzers:
        # Performance
        n_plus_one:
            enabled: true
            threshold: 5

        slow_query:
            enabled: true
            threshold: 100  # milliseconds

        missing_index:
            enabled: true
            slow_query_threshold: 50
            min_rows_scanned: 1000
            explain_queries: true

        # ... (see section 5 for complete list)

3. Global Settings

3.1 Master Enable/Disable

doctrine_doctor:
    enabled: true

Type: boolean Default: true Description: Global switch for the entire bundle. When false, all analyzers are disabled and the profiler panel is hidden.

Use Cases:

  • Temporarily disable during debugging sessions
  • Environment-specific deactivation (e.g., in staging)

Example:

# config/packages/prod/doctrine_doctor.yaml
doctrine_doctor:
    enabled: false  # Disable in production

4. Analysis Configuration

4.1 Excluding Vendor Entities

doctrine_doctor:
    analysis:
        exclude_third_party_entities: true

Type: boolean Default: true Description: Automatically excludes entities from the vendor/ directory during analysis. This filters out third-party entities from Symfony, Doctrine, FOSUserBundle, and other vendor bundles to provide cleaner, more relevant reports focused on your application code.

How it works:

  • Uses path-based detection (/vendor/ in file path) - 100% reliable
  • Filtering is completely transparent - no changes needed in your code
  • Results are cached per request for optimal performance (~0.1ms overhead)

Example: With this enabled (recommended), entities like Symfony\Component\Security\Core\User\User or FOS\UserBundle\Model\User will be excluded from analysis, while your App\Entity\User will be analyzed normally.

When to disable: Only disable if you need to analyze vendor entity mappings or debug third-party bundle configurations.

4.2 Excluding Query Origins by Path

doctrine_doctor:
    analysis:
        exclude_paths: ['vendor/', 'var/cache/']

Type: array<string> Default: ['vendor/'] Description: Excludes DBAL queries whose origin path contains one of these fragments.


5. Profiler Configuration

5.1 Profiler Visibility

doctrine_doctor:
    profiler:
        show_in_toolbar: true

Type: boolean Default: true Description: Controls whether the "Doctrine Doctor" panel appears in the Symfony Profiler toolbar.

5.2 Debug Information

doctrine_doctor:
    profiler:
        show_debug_info: false

Type: boolean Default: false Description: Displays internal debugging information (analyzer execution times, memory usage, service instances). For development of Doctrine Doctor itself only.

5.3 Internal Debug Mode

doctrine_doctor:
    debug:
        enabled: false
        internal_logging: false

Type: boolean Defaults: false Description:

  • debug.enabled: Enables contributor-oriented debug behavior.
  • debug.internal_logging: Enables internal analyzer logs (can add noticeable overhead).

5.4 Enabling Query Backtraces

To see code location backtraces in Doctrine Doctor issues, enable Doctrine DBAL's backtrace collection:

# config/packages/dev/doctrine.yaml
doctrine:
    dbal:
        profiling_collect_backtrace: true

Type: boolean Default: false Description: Enables collection of stack traces for SQL queries, allowing Doctrine Doctor to show exactly where in your code each issue originates.

Note: This is a Doctrine DBAL setting, not a Doctrine Doctor configuration. Add it to your doctrine.yaml file. Recommended for development environments only (minimal performance overhead ~2-5%).


6. Analyzer Configuration

6.1 Performance Analyzers

N+1 Query Analyzer

doctrine_doctor:
    analyzers:
        n_plus_one:
            enabled: true
            threshold: 5
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
threshold integer 5 Minimum duplicate query occurrences to trigger detection

Tuning Guide:

  • Strict: threshold: 2 - Catch even minor N+1 issues
  • Balanced: threshold: 5 - Default, good signal-to-noise ratio
  • Permissive: threshold: 10 - Only major N+1 problems

Slow Query Analyzer

doctrine_doctor:
    analyzers:
        slow_query:
            enabled: true
            threshold: 100
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
threshold integer 100 Execution time threshold in milliseconds

Tuning by Environment:

# Local development (fast SSD)
threshold: 20

# Shared development server
threshold: 50

# Staging (production-like hardware)
threshold: 100

Missing Index Analyzer

doctrine_doctor:
    analyzers:
        missing_index:
            enabled: true
            slow_query_threshold: 100
            min_rows_scanned: 1000
            explain_queries: true
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
slow_query_threshold integer 100 Minimum execution time (ms) to trigger EXPLAIN analysis
min_rows_scanned integer 1000 Minimum rows scanned to recommend index
explain_queries boolean true Execute EXPLAIN queries (requires database permissions)

Database Permission Requirements:

-- MySQL: Ensure user can execute EXPLAIN
GRANT SELECT ON database.* TO 'app_user'@'localhost';

-- PostgreSQL: EXPLAIN requires SELECT permission
-- No additional permissions needed

Performance Considerations:

  • explain_queries: false - Disable if database user lacks permissions or for performance
  • Higher min_rows_scanned reduces false positives on small tables

Hydration Analyzer

doctrine_doctor:
    analyzers:
        hydration:
            enabled: true
            row_threshold: 99
            critical_threshold: 999
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
row_threshold integer 99 Rows to trigger warning severity
critical_threshold integer 999 Rows to trigger "Critical" severity

Flush in Loop Analyzer

doctrine_doctor:
    analyzers:
        flush_in_loop:
            enabled: true
            flush_count_threshold: 5
            time_window_ms: 1000
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
flush_count_threshold integer 5 Minimum flush calls to detect loop pattern
time_window_ms integer 1000 Time window (ms) to group flush calls

Eager Loading Analyzer

doctrine_doctor:
    analyzers:
        eager_loading:
            enabled: true
            join_threshold: 4
            critical_join_threshold: 7
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
join_threshold integer 4 Number of JOINs to trigger info/warning severity
critical_join_threshold integer 7 Number of JOINs to trigger critical severity

Lazy Loading Analyzer

doctrine_doctor:
    analyzers:
        lazy_loading:
            enabled: true
            threshold: 10
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
threshold integer 10 Minimum lazy load events to trigger detection

Bulk Operation Analyzer

doctrine_doctor:
    analyzers:
        bulk_operation:
            enabled: true
            threshold: 20
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
threshold integer 20 Entity count to recommend DQL bulk operations

Recommendation:

// Below threshold: ORM is acceptable
foreach ($entities as $entity) {
    $em->remove($entity);
}
$em->flush();

// Above threshold: Use DQL
$qb->delete(Entity::class, 'e')
   ->where('e.status = :status')
   ->setParameter('status', 'inactive')
   ->getQuery()
   ->execute();

Entity Manager Clear Analyzer

doctrine_doctor:
    analyzers:
        entity_manager_clear:
            enabled: true
            batch_size_threshold: 20
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
batch_size_threshold integer 20 Entity count to recommend clear() calls

Join Optimization Analyzer

doctrine_doctor:
    analyzers:
        join_optimization:
            enabled: true
            max_joins_recommended: 5
            max_joins_critical: 8
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
max_joins_recommended integer 5 Recommended maximum JOINs
max_joins_critical integer 8 Critical threshold

Partial Object Analyzer

doctrine_doctor:
    analyzers:
        partial_object:
            enabled: true
            threshold: 5
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
threshold integer 5 Minimum fields loaded to suggest partial objects

Find All Analyzer

doctrine_doctor:
    analyzers:
        find_all:
            enabled: true
            threshold: 99
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
threshold integer 99 Row count to flag findAll() usage

Get Reference Analyzer

doctrine_doctor:
    analyzers:
        get_reference:
            enabled: true
            threshold: 2
Parameter Type Default Description
enabled boolean true Enable/disable analyzer
threshold integer 2 Minimum find() calls to recommend getReference()

5.2 Security Analyzers

All security analyzers use enabled parameter only (no thresholds):

doctrine_doctor:
    analyzers:
        dql_injection:
            enabled: true
        sql_injection_in_raw_queries:
            enabled: true
        sensitive_data_exposure:
            enabled: true
        insecure_random:
            enabled: true

Security Best Practice: Keep all security analyzers enabled at all times.


5.3 Integrity Analyzers

Integrity analyzers typically have no configurable parameters beyond enabled:

doctrine_doctor:
    analyzers:
        cascade_configuration:
            enabled: true
        cascade_all:
            enabled: true
        bidirectional_consistency:
            enabled: true
        orphan_removal_without_cascade_remove:
            enabled: true
        # ... (see full list in user-guide/analyzers)

5.4 Configuration Analyzers

doctrine_doctor:
    analyzers:
        strict_mode:
            enabled: true
        charset:
            enabled: true
        inno_db_engine:
            enabled: true
        connection_pooling:
            enabled: true
        doctrine_cache:
            enabled: true

Note: Some configuration analyzers are active but currently do not expose dedicated analyzers.<key> toggles in the configuration tree.


5.5 Integrity / Best-Practices Analyzers

doctrine_doctor:
    analyzers:
        naming_convention:
            enabled: true
        collection_initialization:
            enabled: true
        missing_embeddable_opportunity:
            enabled: true
        blameable_trait:
            enabled: true

7. Performance Thresholds

7.1 Recommended Thresholds by Environment

Local Development

doctrine_doctor:
    analyzers:
        slow_query:
            threshold: 10  # Fast local database
        n_plus_one:
            threshold: 2   # Strict detection
        missing_index:
            min_rows_scanned: 500  # Detect early

Shared Development Server

doctrine_doctor:
    analyzers:
        slow_query:
            threshold: 50
        n_plus_one:
            threshold: 3
        missing_index:
            min_rows_scanned: 1000

Staging (Production-like)

doctrine_doctor:
    analyzers:
        slow_query:
            threshold: 100
        n_plus_one:
            threshold: 5  # Reduce noise
        missing_index:
            min_rows_scanned: 5000  # Production-scale data

8. Group Management

⚠️ Note: Group-based configuration (groups: node) is not yet implemented.

To enable/disable specific analyzers, use individual analyzer configuration:

doctrine_doctor:
    analyzers:
        n_plus_one:
            enabled: false  # Disable specific analyzer
        slow_query:
            enabled: true   # Keep enabled

This feature is planned for a future release to allow bulk enable/disable by category.


9. Environment-Specific Configuration

9.1 Development Configuration

# config/packages/dev/doctrine_doctor.yaml
doctrine_doctor:
    enabled: true

    profiler:
        show_in_toolbar: true
        show_debug_info: true  # Show analyzer performance metrics

    analyzers:
        n_plus_one:
            threshold: 2  # Strict

        slow_query:
            threshold: 20  # Fast local DB

        missing_index:
            explain_queries: true

9.2 Test Configuration

# config/packages/test/doctrine_doctor.yaml
doctrine_doctor:
    enabled: false  # Disable to avoid test overhead

9.3 Production Configuration

# config/packages/prod/doctrine_doctor.yaml
doctrine_doctor:
    enabled: false  # MUST be disabled in production

Critical: Doctrine Doctor should NEVER run in production. The bundle is excluded from production via:

  • composer require --dev
  • Explicit enabled: false in prod configuration

10. Advanced Configuration

10.1 Custom Analyzer Registration

# config/services.yaml
services:
    App\Analyzer\CustomBusinessRuleAnalyzer:
        arguments:
            $threshold: 50
            $templateRenderer: '[@AhmedBhs](https://github.com/AhmedBhs)\DoctrineDoctor\Template\Renderer\TemplateRendererInterface'
        tags:
            - { name: 'doctrine_doctor.analyzer' }

10.2 Custom Template Renderer

services:
    App\Infrastructure\MarkdownTemplateRenderer:
        arguments:
            $templateDirectory: '%kernel.project_dir%/templates/doctrine_doctor'

    # Override default renderer
    AhmedBhs\DoctrineDoctor\Template\Renderer\TemplateRendererInterface:
        alias: App\Infrastructure\MarkdownTemplateRenderer

10.3 Service Decoration

services:
    App\Decorator\EnhancedIssueFactory:
        decorates: AhmedBhs\DoctrineDoctor\Factory\IssueFactoryInterface
        arguments:
            $inner: '@.inner'
            $logger: '[@logger](https://github.com/logger)'

10.4 Conditional Configuration via Environment Variables

# config/packages/doctrine_doctor.yaml
doctrine_doctor:
    enabled: '%env(bool:DOCTRINE_DOCTOR_ENABLED)%'

    analyzers:
        slow_query:
            threshold: '%env(int:SLOW_QUERY_THRESHOLD)%'
# .env.local
DOCTRINE_DOCTOR_ENABLED=true
SLOW_QUERY_THRESHOLD=30

Configuration Validation

Validate Configuration Syntax

# Check YAML syntax
php bin/console lint:yaml config/packages/doctrine_doctor.yaml

# Validate container configuration
php bin/console debug:config doctrine_doctor

# Dump complete merged configuration
php bin/console debug:config doctrine_doctor --resolve-env

Common Configuration Errors

1. Invalid Threshold Type

# 📢 Wrong
doctrine_doctor:
    analyzers:
        slow_query:
            threshold: "50"  # String instead of integer

# Correct
doctrine_doctor:
    analyzers:
        slow_query:
            threshold: 50

2. Unknown Analyzer Name

# 📢 Wrong (typo)
doctrine_doctor:
    analyzers:
        n_pluss_one:  # Typo
            enabled: true

# Correct
doctrine_doctor:
    analyzers:
        n_plus_one:
            enabled: true

3. Missing Required Parameters

# 📢 Incomplete
doctrine_doctor:
    analyzers:
        missing_index:
            enabled: true
            # Optional overrides omitted (defaults are used)

# Complete
doctrine_doctor:
    analyzers:
        missing_index:
            enabled: true
            slow_query_threshold: 50
            min_rows_scanned: 1000
            explain_queries: true

Configuration Examples

Minimal Configuration (Use Defaults)

# config/packages/dev/doctrine_doctor.yaml
doctrine_doctor:
    enabled: true

Performance-Focused Configuration

doctrine_doctor:
    analyzers:
        n_plus_one:
            threshold: 2

        slow_query:
            threshold: 25

        missing_index:
            slow_query_threshold: 50
            min_rows_scanned: 500

Security-Focused Configuration

doctrine_doctor:
    # Enable only security analyzers individually
    analyzers:
        dql_injection:
            enabled: true
        sql_injection_in_raw_queries:
            enabled: true
        sensitive_data_exposure:
            enabled: true
        # Disable performance analyzers
        n_plus_one:
            enabled: false
        slow_query:
            enabled: false

Full Customization

doctrine_doctor:
    enabled: true

    profiler:
        show_in_toolbar: true
        show_debug_info: false

    analyzers:
        n_plus_one:
            enabled: true
            threshold: 5

        slow_query:
            enabled: true
            threshold: 100

        missing_index:
            enabled: true
            slow_query_threshold: 50
            min_rows_scanned: 1000
            explain_queries: true

        hydration:
            enabled: true
            row_threshold: 99
            critical_threshold: 999

        flush_in_loop:
            enabled: true
            flush_count_threshold: 5
            time_window_ms: 1000

        eager_loading:
            enabled: true
            join_threshold: 4
            critical_join_threshold: 7

        lazy_loading:
            enabled: true
            threshold: 10

        bulk_operation:
            enabled: true
            threshold: 20

        entity_manager_clear:
            enabled: true
            batch_size_threshold: 20

        join_optimization:
            enabled: true
            max_joins_recommended: 5
            max_joins_critical: 8

        partial_object:
            enabled: true
            threshold: 5

        find_all:
            enabled: true
            threshold: 99

        get_reference:
            enabled: true
            threshold: 2

        # Security (no thresholds)
        dql_injection:
            enabled: true
        sql_injection_in_raw_queries:
            enabled: true
        sensitive_data_exposure:
            enabled: true
        insecure_random:
            enabled: true

        # Integrity (no thresholds)
        cascade_configuration:
            enabled: true
        cascade_all:
            enabled: true
        bidirectional_consistency:
            enabled: true

        # Configuration (no thresholds)
        strict_mode:...
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
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