PHPackages                             danydev/n-plus-one-detector - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. danydev/n-plus-one-detector

ActiveProject[Database &amp; ORM](/categories/database)

danydev/n-plus-one-detector
===========================

Utility that detects n+1 queries triggered by doctrine orm

15PHP

Since Aug 11Pushed 5y ago1 watchersCompare

[ Source](https://github.com/danydev/doctrine-n-plus-one-detector)[ Packagist](https://packagist.org/packages/danydev/n-plus-one-detector)[ RSS](/packages/danydev-n-plus-one-detector/feed)WikiDiscussions master Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

Doctrine N plus one detector
============================

[](#doctrine-n-plus-one-detector)

Motivation
----------

[](#motivation)

When working with an orm you need to deal with the n+1 queries problem. If you are not familiar with it, you can read more about it [here](https://symfonycasts.com/screencast/doctrine-relations/join-n-plus-one). In a few words it's when the orm does n+1 queries as result of your code accessing lazily loaded entities.

The remediation for the n+1 is rather easy, it consists in eager loading the relations causing the n+1 (either by fetch joining them or for doctrine even better with a [partial hydration](http://ocramius.github.io/blog/doctrine-orm-optimization-hydration)). Those adhoc fixes are in the parts of the application that fetch the root entity for the specific use case. What to eager load can't be statically defined at load time because it really depends on how the fetched entities are going to be used later on.

While the n+1 problem is well understood by most developers, due to the nature of the problem is rather easy to let slip an n+1 while doing some application changes. Think about cases where people use entities in their template engine, and they just fulfil a new requirement showing a bit more information triggering a new n+1. Or think about cases where a central entity is refactored to replace a scalar property with an x-to-one relation, thus you need to perform a careful analysis of each use of the refactored method to see if you need n+1 fixes. That's where doctrine n+1 detector comes into place. Once enabled it will listen to some doctrine events detecting n+1 queries triggered by doctrine and eventually it will log them so that the user can inspect them later (or maybe create alarms around those logs if he prefers it). In other words you still need to eager load to avoid n+1 queries, but in case some n+1 slip inadvertently in production you have a tool to make you aware about it so that you can fix them sooner than later.

Installation
------------

[](#installation)

You can install the package with composer:

```
composer require danydev/n-plus-one-detector

```

Usage
-----

[](#usage)

You need to initialize the detector and call `start` as soon as you want to start detecting n+1, finally later on the request lifecycle you can inspect all the n+1 detected.

```
// Start the n+1 detector at the start of our request handler.
$nPlusOneDetector = new NPlusOneDetector($entityManager);
$nPlusOneDetector->start();

//... normal request lifecycle happens here...

// Inspect n+1 detected just before returning the response
$result = $nPlusOneDetector->getDetectedNPlusOne();
foreach($result->getCollectionStats() as $stat) {
    error_log('[N+1-detected] on ' . $stat->getOwnerClass() . ' due to collection of ' . $stat->collectionElementsClass());
}
foreach($result->getProxyStats() as $stat) {
    error_log('[N+1-detected] on ' . $stat->getClass());
}

```

TODO
----

[](#todo)

- PSR-15 middleware that does the start and stop, configurable with an optional PSR-3 logger.
- Symfony bundle to integrate with their HttpKernel.
- Detect n+1 generated by non-owning side one-to-one (this n+1 is by design in doctrine, but it may be valuable for the user to be notified about it).
- Detect n+1 generated by \*-to-many used in classes with an abstract parent (this n+1 is by design in doctrine, but it may be valuable for the user to be notified about it).
- Write some tests.
- Apply/enforce phpcs, psalm/phpstan on ci.

###  Health Score

17

—

LowBetter than 6% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2708453?v=4)[Daniele Orru'](/maintainers/danydev)[@danydev](https://github.com/danydev)

---

Top Contributors

[![danydev](https://avatars.githubusercontent.com/u/2708453?v=4)](https://github.com/danydev "danydev (1 commits)")

### Embed Badge

![Health badge](/badges/danydev-n-plus-one-detector/health.svg)

```
[![Health](https://phpackages.com/badges/danydev-n-plus-one-detector/health.svg)](https://phpackages.com/packages/danydev-n-plus-one-detector)
```

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[mongodb/mongodb

MongoDB driver library

1.6k64.0M546](/packages/mongodb-mongodb)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90340.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
