From 7bf77489087a1838eb54accf08579a2410fd4b6b Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 24 Sep 2026 13:48:29 +0200 Subject: [PATCH] ResultSet: Fix incorrect count due to delayed iteration `ResultSet::advance()` is now responsible to keep track of both the position and count while the original generator is still being traversed. Once it is exhausted, the count does not change anymore in case the cache is enabled. --- src/ResultSet.php | 14 +++++++++----- tests/ResultSetTest.php | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ResultSet.php b/src/ResultSet.php index 5977d76..f1c8a2b 100644 --- a/src/ResultSet.php +++ b/src/ResultSet.php @@ -89,6 +89,7 @@ public function hasResult(): bool public function current() { if ($this->position === null) { + $this->count = 0; $this->advance(); } @@ -102,10 +103,6 @@ public function next(): void } if ($this->isCacheDisabled || ! $this->cache->valid()) { - // Raise count during the first loop only after each iteration, so - // that it is synchronized with how many times a loop has been run. - $this->count += 1; - $this->generator->next(); $this->advance(); } else { @@ -116,6 +113,7 @@ public function next(): void public function key(): int { if ($this->position === null) { + $this->count = 0; $this->advance(); } @@ -138,8 +136,8 @@ public function rewind(): void } if ($this->position === null) { - $this->advance(); $this->count = 0; + $this->advance(); } else { $this->position = 0; } @@ -176,6 +174,12 @@ protected function advance(): void } else { $this->position += 1; } + + if ($this->limit === null || $this->position < $this->limit) { + // Raise count during the first loop only after each iteration, so + // that it is synchronized with how many times a loop has been run. + $this->count += 1; + } } /** diff --git a/tests/ResultSetTest.php b/tests/ResultSetTest.php index 5d48a74..1e3fd08 100644 --- a/tests/ResultSetTest.php +++ b/tests/ResultSetTest.php @@ -201,6 +201,7 @@ public function testCountWithCacheBeforeIteration(): void } $this->assertSame(['a', 'b', 'c'], $result); + $this->assertSame(3, $set->count(), 'Count must not change due to iteration'); } public function testLimitedCountWithCacheBeforeIteration(): void