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.
OverprivilegedDatabaseUserAnalyzer: detects privileged, empty, or passwordless database users and suggests switching to a least-privilege account.HardcodedDatabaseCredentialsAnalyzer: detects database credentials embedded directly in DBAL configuration and suggests moving them to environment variables.NPlusOneAnalyzer: identifies repeated findBy()/findOneBy()-style lookups on non-key columns and suggests batching with IN queries or request-level caching.SensitiveDataExposureAnalyzer: now also flags public getters that expose sensitive entity fields without explicit protection.PropertyTypeMismatchAnalyzer: now attaches concrete fix suggestions for PHP/Doctrine type mismatches, including nullability mismatches.CollectionInitializationAnalyzer suggestion template now uses the actual mappedBy value when available.CollectionInitializationAnalyzer: now supports PHP constructor promotion when detecting collection initialization, fixing the false positive reported in #67.CollectionEmptyAccessAnalyzer in favor of the AST-based collection initialization analysis path.SQLInjectionInRawQueriesAnalyzer: now detects unparameterized literals in WHERE clauses of raw SQL queries as an injection risk, instead of only flagging active attack patterns.DQLInjectionAnalyzer: now detects Doctrine-generated SQL with concatenated literals and empty bound parameters, indicating unsafe DQL string concatenation.OnDeleteCascadeMismatchAnalyzer now assigns CRITICAL severity for orm_cascade_db_setnull and orm_orphan_db_setnull mismatcheson_delete_cascade_mismatch now render context-aware code snippets per mismatch typeOneToOneInverseSideAnalyzer: detects bidirectional OneToOne mappedBy sides that silently force Doctrine to execute N+1 queries on every load, even when the relation is never accessed. Suggests flipping the owning side, going unidirectional, or using a fetch joinone_to_one_inverse_side analyzerCompositeKeyComplexityAnalyzer: use ShortClassNameTrait, proper return types, and MappingHelper for Doctrine 2/3/4 compatibilityCompositeKeyComplexityAnalyzer: detects entities using composite primary keys that limit Doctrine ORM features (no getReference(), slower identity map, complex FK mappings). Severity: WARNING for 2 columns, CRITICAL for 3+ or when referenced by other entitiescomposite_key_complexity analyzerOnDeleteCascadeMismatchAnalyzer now assigns CRITICAL severity for orm_cascade_db_setnull and orm_orphan_db_setnull mismatches (previously WARNING)on_delete_cascade_mismatch now render context-aware code snippets per mismatch type instead of a generic templateJoinColumnNonPrimaryKeyAnalyzer: detects associations where referencedColumnName points to a non-primary-key columnDuplicatePrivateFieldInHierarchyAnalyzer: detects private fields with the same name in an entity and its mapped parent classesSuggested Fix, Hide suggestion).issue-body background color to #fffefc for better visual consistency.isset.initializedProperty error: use ReflectionProperty::isInitialized() for readonly property check after unserialization.rel="noopener noreferrer" on external Doctrine documentation link.isset.initializedProperty error: use ReflectionProperty::isInitialized() for readonly property check after unserialization.rel="noopener noreferrer" on external Doctrine documentation link (target="_blank")..alert-warning, .alert-danger, and .dd-suggestion-meta-intro blocks (less aggressive text contrast).IssueReconstructor (#32)<pre><code> to prevent entity encoding (direct commit 0d8d54e)webmozart/assert constraint to support v2.x (direct commit b4fe7b6)bitbag/coding-standard dependency (direct commit e7b59ae)0c70d90)webmozart/assert constraint to support v2.x (direct commit b4fe7b6)bitbag/coding-standard dependency (direct commit e7b59ae)IssueReconstructor type validation,PropertyTypeMismatchAnalyzer fixtures and fix SafeContext test.c71ebaf, f12e90f, b19d58e).23ff95a.First stable release of the 2.x series. Requires PHP 8.4+, Doctrine Bundle 3 and Doctrine ORM 3/4.
IssueReconstructor was instantiated without the template renderer after Symfony profiler deserializationSafeContext::offsetGet() now returns null for missing keys instead of throwing, so templates with optional context variables (like trigger_location) no longer crasheager_loading template missing trigger_location keyleft_join_with_not_null template wrong context keydoctrine/doctrine-bundle ^3.0 (drop ^2.x)doctrine/orm ^3.0|^4.0 (drop ^2.x)webmozart/assert ^1.12#[\Override], typed constants, array_find())Upgrading from 1.x? Update your composer.json to "ahmed-bhs/doctrine-doctor": "^2.0" and ensure you run Doctrine Bundle 3 with Doctrine ORM 3+.
Full Changelog: https://github.com/ahmed-bhs/doctrine-doctor/compare/v1.0.0...v1.0.1
PgiRedmineProject::$projects instead of generic redmineProject)PgiProjectCrudController::{closure}() in PgiProjectCrudController.php:267)collection_eager_loading.php with context-aware solutions (addSelect vs EXTRA_LAZY)decimal/bigint type mapping (returns string, not float)Full Changelog: https://github.com/ahmed-bhs/doctrine-doctor/compare/v1.0.1...v1.0.2
Runtime analysis tool for Doctrine ORM integrated into Symfony Web Profiler.
composer require --dev ahmed-bhs/doctrine-doctor
Auto-configured via Symfony Flex.
| Category | Count | Examples |
|---|---|---|
| Performance | 25 | N+1 queries, missing indexes, slow queries, hydration |
| Security | 4 | DQL/SQL injection, sensitive data exposure |
| Code Quality | 29 | Cascade config, type mismatches, architectural violations |
| Configuration | 8 | Charset, timezone, Gedmo traits, database setup |
https://github.com/ahmed-bhs/doctrine-doctor/compare/v1.1.0-alpha.3...v1.0.0
How can I help you explore Laravel packages today?