Doctrine Doctor
Runtime Analysis Tool for Doctrine ORM — Integrated into Symfony Web Profiler
Get started now View on GitHub
Why Runtime Analysis?
Unlike static analysis tools (PHPStan, Psalm) that analyze code without execution, Doctrine Doctor:
- Detects runtime-only issues: N+1 queries, actual query performance, missing indexes on real database
- Analyzes real execution context: Actual parameter values, data volumes, execution plans
- Integrated into your workflow: Results appear directly in Symfony Web Profiler during development
- 📍 Backtrace: Points to exact template line
- 💡 Suggestion: Use
->addSelect(..)to eager load authors
Features
90+ Specialized Analyzers
-
Performance — Detects N+1 queries, missing database indexes, slow queries, excessive hydration, findAll() without limits, setMaxResults() with collection joins, too many JOINs, and query caching opportunities
-
Security — Identifies DQL/SQL injection vulnerabilities, QueryBuilder SQL injection risks, sensitive data exposure in serialization, unprotected sensitive fields, and insecure random generators
-
Code Quality — Detects cascade configuration issues, bidirectional inconsistencies, missing orphan removal, type mismatches, float usage for money, uninitialized collections, EntityManager in entities, and architectural violations
-
Configuration — Validates database charset/collation settings, timezone handling, Gedmo trait configurations, MySQL strict mode, and other database-level configurations
⚡ Quick Start (30 seconds)
Step 1: Install
composer require --dev ahmed-bhs/doctrine-doctor
Step 2: That’s it!
Auto-configured via Symfony Flex. No YAML, no configuration files needed.
Step 3: See it in action
- Refresh any page in your Symfony app (in
devenvironment) - Open the Symfony Web Profiler (bottom toolbar)
- Click the “Doctrine Doctor” panel 🩺
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
Full configuration reference →
Example: N+1 Query Detection
Problem: Template triggers lazy loading
// Controller
$users = $repository->findAll();
// Template
{% for user in users %}
{{ user.profile.bio }}
{% endfor %}
Triggers 100 queries
Detection: Doctrine Doctor detects N+1
- 100 queries instead of 1
- Shows exact query count, execution time
- Suggests eager loading
Real-time detection
Solution: Eager load with JOIN
$users = $repository
->createQueryBuilder('u')
->leftJoin('u.profile', 'p')
->addSelect('p')
->getQuery()
->getResult();
Single query
Documentation
| Document | Description |
|---|---|
| Configuration Reference | Comprehensive guide to all configuration options - customize analyzers, thresholds, and outputs to match your workflow |
| Full Analyzers List | Complete catalog of all 90+ analyzers covering performance, security, code quality, and configuration |
| Architecture Guide | Deep dive into system design, architecture patterns, and technical internals |
| Template Security | Essential security best practices for PHP templates - prevent XSS attacks and ensure safe template rendering |
Contributing
We welcome contributions! See our Contributing Guide for details.
License
MIT License - see LICENSE for details.
Created by Ahmed EBEN HASSINE
