Skip to content

Commit 269792c

Browse files
committed
iterateBatch
1 parent f4955b2 commit 269792c

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

packages/query/src/Query.php

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,46 @@ public function __call(string $name, array $args): mixed
18401840
/**
18411841
* @template T of Collection
18421842
*
1843+
* Iterate and call DB every N times, every time get full items but yield item one by one, stop when no more items.
1844+
* This method can ensure no long connection to DB. You only need one level foreach to get every item.
1845+
*
1846+
* @param int $length
1847+
* @param class-string<T>|null $class
1848+
* @param array $args
1849+
*
1850+
* @return Generator<Collection<T>>
1851+
*/
1852+
public function iterateBatched(int $length, ?string $class = null, array $args = []): \Generator
1853+
{
1854+
$offset = 0;
1855+
1856+
while (true) {
1857+
$query = clone $this;
1858+
$query->offset($offset)->limit($length);
1859+
1860+
$items = $query->all($class, $args);
1861+
1862+
$count = 0;
1863+
1864+
foreach ($items as $item) {
1865+
$count++;
1866+
yield $item;
1867+
}
1868+
1869+
if ($count === 0 || $count < $length) {
1870+
break;
1871+
}
1872+
1873+
$offset += $length;
1874+
}
1875+
}
1876+
1877+
/**
1878+
* @template T of Collection
1879+
*
1880+
* Iterate and return chunks of items, every chunk will one time return full items.
1881+
* You need 2 level foreach to get every item.
1882+
*
18431883
* @param int $length
18441884
* @param class-string<T>|null $class
18451885
* @param array $args
@@ -1873,11 +1913,15 @@ public function iterateChunks(int $length, ?string $class = null, array $args =
18731913
/**
18741914
* @template T of Collection
18751915
*
1916+
* Iterate and call DB N times, every time get innter iterator and yield items one by one, stop when no more items.
1917+
* This method will not offset or paginated, it will always start from 0.
1918+
* You must change the item state in the loop to avoid infinite loop.
1919+
*
18761920
* @param int $length
18771921
* @param class-string<T>|null $class
18781922
* @param array $args
18791923
*
1880-
* @return Generator<Collection<T>>
1924+
* @return Generator<T>
18811925
*/
18821926
public function iterateWhile(int $length, ?string $class = null, array $args = []): \Generator
18831927
{
@@ -1900,6 +1944,41 @@ public function iterateWhile(int $length, ?string $class = null, array $args = [
19001944
}
19011945
}
19021946

1947+
/**
1948+
* @template T of Collection
1949+
*
1950+
* Iterate and call DB N times, every time get full items and yield items one by one to prevent long connections,
1951+
* stop when no more items.
1952+
* This method will not offset or paginated, it will always start from 0.
1953+
* You must change the item state in the loop to avoid infinite loop.
1954+
*
1955+
* @param int $length
1956+
* @param class-string<T>|null $class
1957+
* @param array $args
1958+
*
1959+
* @return Generator<T>
1960+
*/
1961+
public function iterateBatchWhile(int $length, ?string $class = null, array $args = []): \Generator
1962+
{
1963+
$query = clone $this;
1964+
$query->offset(0)->limit($length);
1965+
1966+
while (true) {
1967+
$items = $query->all($class, $args);
1968+
1969+
$count = 0;
1970+
1971+
foreach ($items as $item) {
1972+
$count++;
1973+
yield $item;
1974+
}
1975+
1976+
if ($count === 0 || $count < $length) {
1977+
break;
1978+
}
1979+
}
1980+
}
1981+
19031982
/**
19041983
* @template T of Collection
19051984
*

0 commit comments

Comments
 (0)