From 1abc5d31b2006e4e3d43447aa9bffb24ed154c61 Mon Sep 17 00:00:00 2001 From: KalimeroMK Date: Tue, 20 Oct 2026 12:36:12 +0200 Subject: [PATCH 1/3] Leave array rows to the query instead of checking each model --- src/ActiveQuery.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ActiveQuery.php b/src/ActiveQuery.php index 0b1b2cad3..c51f14c12 100644 --- a/src/ActiveQuery.php +++ b/src/ActiveQuery.php @@ -321,7 +321,8 @@ public function populate(array $rows): array $models = $this->createModels($rows); - if (count($models) > 1) { + if (!$this->asArray && count($models) > 1) { + /** @var ActiveRecordInterface[] $models */ LazyLoadGuard::registerResultSet($models); } From f4eec7c6f11e54d49b5b1a0decd64b07f573efca Mon Sep 17 00:00:00 2001 From: KalimeroMK Date: Tue, 20 Oct 2026 12:36:12 +0200 Subject: [PATCH 2/3] Report lazy loads only for records of a registered result set --- src/LazyLoadGuard.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/LazyLoadGuard.php b/src/LazyLoadGuard.php index ac79b7197..bfe7b7ebb 100644 --- a/src/LazyLoadGuard.php +++ b/src/LazyLoadGuard.php @@ -54,7 +54,7 @@ public static function set(LazyLoadGuardMode $mode, ?LoggerInterface $logger = n * the same result set, which is an N+1 query, from the same relation loaded by records that were each * fetched by a query of their own, which has nothing to eager load across. * - * @param ActiveRecordInterface[]|array[] $models The models populated from one result set. + * @param ActiveRecordInterface[] $models The models populated from one result set. * * @see ActiveQuery::populate() */ @@ -64,7 +64,7 @@ public static function registerResultSet(array $models): void $resultSet = null; foreach ($models as $model) { - if (!$model instanceof ActiveRecordInterface || !self::isGuarded($model::class)) { + if (!self::isGuarded($model::class)) { continue; } @@ -89,12 +89,10 @@ public static function check(ActiveRecordInterface $model, string $relationName) $resultSets = self::resultSets(); - /** - * A record populated outside a result set is a result set of its own. - * - * @psalm-suppress PossiblyNullArgument - */ - $resultSets[$model] ??= new LazyLoadResultSet(); + // A record fetched by a query of its own has nothing to eager load across. + if (!isset($resultSets[$model])) { + return; + } /** @psalm-var LazyLoadResultSet $resultSet */ $resultSet = $resultSets[$model]; From 13c25a15ca19b54aaa5b2bd0fe450fa69758e768 Mon Sep 17 00:00:00 2001 From: KalimeroMK Date: Tue, 20 Oct 2026 12:36:51 +0200 Subject: [PATCH 3/3] Add the review follow-up to the lazy-load guard changelog entry --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01d464455..e39b62ae9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,7 @@ ## 1.1.1 under development -- Enh #590, #594: Add `LazyLoadGuardTrait` and `LazyLoadGuard` to detect N+1 queries - (@KalimeroMK) +- Enh #590, #594, #596: Add `LazyLoadGuardTrait` and `LazyLoadGuard` to detect N+1 queries (@KalimeroMK) ## 1.1.0 May 14, 2026