ahmed-bhs / doctrine-doctor
Doctrine ORM checks for Symfony: inspect real request queries in the Web Profiler and run source, mapping, and optional database audits in CI.
Package info
github.com/ahmed-bhs/doctrine-doctor
Type:symfony-bundle
pkg:composer/ahmed-bhs/doctrine-doctor
Fund package maintenance!
Requires
- php: ^8.4
- doctrine/doctrine-bundle: ^3.0
- nikic/php-parser: ^5.6
- phpmyadmin/sql-parser: ^6.0
- symfony/framework-bundle: ^6.0|^7.0|^8.0
- webmozart/assert: ^1.12 || ^2.0
Requires (Dev)
- deptrac/deptrac: ^4.2
- doctrine/orm: ^3.0
- pdepend/pdepend: 3.x-dev
- php-parallel-lint/php-parallel-lint: ^1.4
- phpmd/phpmd: 3.x-dev
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.1
- phpstan/phpstan-doctrine: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^10.0
- rector/rector: ^2.3
- symfony/ai-symfony-mate-extension: ^0.13.0
- symfony/stopwatch: ^6.0|^7.0|^8.0
- symfony/validator: ^8.0
- symfony/var-dumper: ^6.0|^7.0|^8.0
- symfony/var-exporter: ^6.4|^7.0|^8.0
- symplify/easy-coding-standard: ^13.2
- twig/twig: ^3.0
Suggests
- doctrine/orm: Required for ORM-specific analyzers (N+1 detection via metadata, eager loading, entity mapping checks). Without it, only DBAL-native analyzers run.
- symfony/ai-symfony-mate-extension: Required for AI Mate / MCP integration of Doctrine Doctor profiler issues
Provides
None
Conflicts
None
Replaces
None
- dev-main / 2.x-dev
- v2.12.0
- v2.11.2
- v2.11.1
- v2.11.0
- v2.11.0-beta.1
- v2.10.4
- v2.10.3
- v2.10.2
- v2.10.1
- v2.10.0
- v2.9.5
- v2.9.4
- v2.9.3
- v2.9.2
- v2.9.1
- v2.9.0
- v2.9.0-beta.4
- v2.9.0-beta.3
- v2.9.0-beta.2
- v2.9.0-beta.1
- v2.8.6
- v2.8.5
- v2.8.4
- v2.8.3
- v2.8.2
- v2.8.1
- v2.8.0
- v2.8.0-beta.2
- v2.8.0-beta.1
- v2.7.3
- v2.7.2
- v2.7.2-alpha.3
- v2.7.2-alpha.2
- v2.7.2-alpha.1
- v2.7.1
- v2.7.0
- v2.6.0
- v2.5.1
- v2.5.0
- v2.4.0
- v2.3.0
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.3
- v2.1.2
- v2.1.2-beta.3
- v2.1.2-beta.2
- v2.1.2-beta.1
- v2.1.1
- v2.1.0
- v2.1.0-beta.1
- v2.0.1
- v2.0.0
- v2.0.0-beta.4
- v2.0.0-beta.3
- v2.0.0-beta.2
- v2.0.0-beta.1
- 1.x-dev
- v1.1.0
- v1.1.0-alpha.3
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- v0.1.0-beta.4
- v0.1.0-beta.3
- v0.1.0-beta.2
- v0.1.0-beta.1
- v0.1.0-alpha.3
- v0.1.0-alpha.2
- v0.1.0-alpha.1
- dev-fix/lazy-pending-analysis-subscriber
- dev-perf/runtime-analysis-cost
- dev-chore/remove-agent-harness
- dev-claude/sleepy-babbage-hpv84o
- dev-feat/richer-cli-findings
- dev-fix/quote-jekyll-description
- dev-docs/full-width-profiler-composite
- dev-docs/emphasize-profiler-preview
- dev-docs/add-pgi-analysis-capture
- dev-docs/improve-readme-visuals
- dev-chore/add-agent-harness
- dev-feat/runtime-static-analyzer-split
- dev-chore/add-funding-config
- dev-feat/view-collation-mismatch-analyzer
- dev-chore/changelog-2.10.3
- dev-fix/rector-null-coalescing-assign
- dev-fix/docs-jekyll-build
- dev-refactor/extract-query-field-accessors
- dev-docs/complete-analyzer-catalog
- dev-fix/deduplicate-issues-by-type
- dev-chore/simplify-directory-structure
- dev-fix/disambiguate-proxy-autogenerate-titles
- dev-chore/bump-github-actions
- dev-chore/apply-rector-php84-modernization
- dev-feat/discriminator-and-mapping-deprecation-analyzers
- dev-chore/update-doctrine-and-tighten-orm-constraint
- dev-feat/setmaxresults-collection-join-message
- dev-chore/ecs-fix-latest
- dev-feat/ai-mate-ci-coverage
- dev-fix/analyzer-false-positives-hexagonal
- dev-fix/many-to-one-false-positive
- dev-fix/post-merge-hardening
- dev-feat/dbal-only-support
- dev-feat/flush-in-event-listener-analyzer
- dev-feat/many-to-many-extra-columns-analyzer
- dev-feat/lazy-ghost-objects-disabled-analyzer
- dev-lazy-ghost-objects
- dev-feat/eager-loading-mapping-detection
- dev-feat/mutable-datetime-detection
- dev-feat/denormalized-aggregate-without-locking
- dev-feat/unique-entity-without-database-index
- dev-refactor/split-analyzer-interface
- dev-feat/inheritance-integrity-analyzers
- dev-feat/inheritance-strategy-analyzers
- dev-fix/missing-index-false-positive-with-used-key
- dev-fix/xss-backtrace-json-encode
- dev-feature/72-mutable-datetime-analyzer
- dev-feat/security-and-repeated-lookup-analyzers
- dev-fix/constructor-promotion-false-positive
- dev-feat/one-to-one-inverse-side-analyzer
- dev-feat/join-column-and-duplicate-field-analyzers
- dev-fix/harden-unregistered-analyzers
- dev-fix/profiler-ui-related-findings
- dev-chore/profiler-panel-decouple-cleanup
- dev-feat/prismjs-syntax-highlighting
- dev-fix/preserve-concrete-issue-type
- dev-refactor/issue-factory-dynamic-type-map
- dev-fix/issue-deduplicator-preg-match-checks
- dev-refactor/extract-deduplicatable-issue-interface
- dev-refactor/extract-short-class-name-helper
- dev-refactor/issue-enums-consistency
- dev-docs/add-missing-analyzer-docs
- dev-refactor/extract-suggestion-factory-interface
- dev-test/early-return-when-disabled
- dev-fix/validate-class-before-instantiation
- dev-fix/symfony-8-compatibility
- dev-feat/cartesian-product-analyzer
- dev-feature/nplusone-collection-trigger-location
This package is auto-updated.
Last update: 2026-10-07 19:44:34 UTC
README
Find Doctrine ORM problems in the profiler. Catch them in CI.
Get started · Add it to CI · Browse analyzers
Doctrine Doctor adds Doctrine-focused feedback to the two places where it is most useful:
| When you need an answer | Doctrine Doctor helps you |
|---|---|
| A page is slow | Inspect real queries, timings, and backtraces in the Web Profiler. |
| A change is ready for review | Check source code, mappings, and configuration in CI. |
| A database needs a closer look | Run an opt-in audit with --with-database. |
Runtime context with the real CI result kept in view.
Catch issues in CI · Investigate them in the profiler
Choose your feedback loop
What it catches
Doctrine Doctor ships with more than 100 analyzers grouped by the kind of decision they support:
| Area | Examples |
|---|---|
| Performance | N+1 queries, missing indexes, slow queries, excessive hydration, unbounded reads, and inefficient joins |
| Security | DQL/SQL injection, unsafe QueryBuilder input, sensitive data exposure, and insecure randomness |
| Integrity | Cascade and orphan-removal issues, mapping mismatches, type errors, and invalid entity boundaries |
| Configuration | Charset, collation, timezone, strict mode, cache, and platform configuration |
See the full analyzer catalog for the complete list.
Quick start
1. Install the bundle
composer require --dev ahmed-bhs/doctrine-doctor
2. Open a real page
The bundle is auto-configured through Symfony Flex. No YAML is needed for the first run.
3. Read the feedback
Refresh the page in the dev environment, open the Symfony Web Profiler, and select the Doctrine Doctor panel.
Add it to CI
Check your code and mappings on every pull request:
php bin/console doctrine:doctor:analyze --fail-on=warning
The command exits with a failure when it finds a warning or critical issue. Use
--fail-on=critical to fail only on critical issues, --fail-on=info to fail
on every finding, or --fail-on=never to report without failing. Live database
audits are opt-in with --with-database.
See the profiler and CI checks guide for the full analyzer inventory and execution rules.
How the feedback flows
flowchart LR
A[Pull request] --> B[Doctrine Doctor]
B --> C{Finding?}
C -->|No| D[Merge with confidence]
C -->|Yes| E[Analyzer + location + next step]
E --> F[Fix and push]
F --> B
classDef start fill:#dbeafe,stroke:#2563eb,color:#0f172a
classDef check fill:#ede9fe,stroke:#7c3aed,color:#0f172a
classDef finding fill:#fee2e2,stroke:#dc2626,color:#0f172a
classDef done fill:#dcfce7,stroke:#16a34a,color:#0f172a
class A start
class B check
class C,E finding
class D done
Loading
Configuration (optional)
Configure thresholds in config/packages/dev/doctrine_doctor.yaml:
doctrine_doctor: analyzers: n_plus_one: threshold: 5 # default, lower to 3 to be stricter slow_query: threshold: 100 # milliseconds (default)
Enable backtraces to see WHERE in your code issues originate:
# config/packages/dev/doctrine.yaml doctrine: dbal: profiling_collect_backtrace: true
AI Mate / MCP integration (optional)
Doctrine Doctor can expose its profiler findings to AI assistants (Claude Code,
Cursor, GitHub Copilot, …) over MCP through
Symfony AI Mate. It registers an MCP
tool, doctrine-doctor-issues, that reads a profiler request and returns the detected
issues — already sanitized for safe AI consumption.
This is opt-in. The bundle ships the integration code but pulls no AI dependency by default. Without AI Mate installed, this does not apply and Doctrine Doctor runs exactly as before.
Example: N+1 Query Detection
| Before — 100 queries | After — 1 query |
$users = $repository->findAll(); {% for user in users %}
{{ user.profile.bio }}
{% endfor %}
|
$users = $repository ->createQueryBuilder('u') ->leftJoin('u.profile', 'p') ->addSelect('p') ->getQuery() ->getResult(); |
|
Doctrine Doctor detects the N+1 pattern at runtime — reports query count,
execution time, points to the exact template line, and suggests eager loading with |
|
Documentation
| Document | Description |
|---|---|
| Full Analyzers List | Browse the built-in checks for performance, security, integrity, and configuration |
| Profiler and CI Checks | A quick guide to choosing where to run each check |
| Architecture Guide | Deep dive into system design, architecture patterns, and technical internals - understand how Doctrine Doctor works under the hood |
| Configuration Reference | Comprehensive guide to all configuration options - customize analyzers, thresholds, and outputs to match your workflow |
| Template Security | Essential security best practices for PHP templates - prevent XSS attacks and ensure safe template rendering |
| AI Mate / MCP integration | Optional AI assistant integration - expose profiler issues to Claude Code, Cursor, and other MCP clients through Symfony AI Mate |
Contributing
See Contributing Guide for guidelines.
License
MIT License - see LICENSE for details.
Created by Ahmed EBEN HASSINE

