Skip to content

Commit 6d2fb50

Browse files
Implement chunkById in descending order
1 parent cddb4f3 commit 6d2fb50

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/Illuminate/Database/Concerns/BuildsQueries.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,35 @@ public function each(callable $callback, $count = 1000)
112112
* @return bool
113113
*/
114114
public function chunkById($count, callable $callback, $column = null, $alias = null)
115+
{
116+
return $this->orderedChunkById($count, $callback, $column, $alias);
117+
}
118+
119+
/**
120+
* Chunk the results of a query by comparing IDs in descending order.
121+
*
122+
* @param int $count
123+
* @param callable $callback
124+
* @param string|null $column
125+
* @param string|null $alias
126+
* @return bool
127+
*/
128+
public function chunkByIdDesc($count, callable $callback, $column = null, $alias = null)
129+
{
130+
return $this->orderedChunkById($count, $callback, $column, $alias, true);
131+
}
132+
133+
/**
134+
* Chunk the results of a query by comparing IDs in a given order.
135+
*
136+
* @param int $count
137+
* @param callable $callback
138+
* @param string|null $column
139+
* @param string|null $alias
140+
* @param bool $descending
141+
* @return bool
142+
*/
143+
public function orderedChunkById($count, callable $callback, $column = null, $alias = null, $descending = false)
115144
{
116145
$column ??= $this->defaultKeyName();
117146

@@ -127,7 +156,11 @@ public function chunkById($count, callable $callback, $column = null, $alias = n
127156
// We'll execute the query for the given page and get the results. If there are
128157
// no results we can just break and return from here. When there are results
129158
// we will call the callback with the current chunk of these results here.
130-
$results = $clone->forPageAfterId($count, $lastId, $column)->get();
159+
if($descending){
160+
$results = $clone->forPageBeforeId($count, $lastId, $column)->get();
161+
} else {
162+
$results = $clone->forPageAfterId($count, $lastId, $column)->get();
163+
}
131164

132165
$countResults = $results->count();
133166

tests/Database/DatabaseQueryBuilderTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4421,6 +4421,26 @@ public function testChunkPaginatesUsingIdWithAlias()
44214421
}, 'table.id', 'table_id');
44224422
}
44234423

4424+
public function testChunkPaginatesUsingIdDesc()
4425+
{
4426+
$builder = $this->getMockQueryBuilder();
4427+
$builder->orders[] = ['column' => 'foobar', 'direction' => 'desc'];
4428+
4429+
$chunk1 = collect([(object) ['someIdField' => 10], (object) ['someIdField' => 1]]);
4430+
$chunk2 = collect([]);
4431+
$builder->shouldReceive('forPageBeforeId')->once()->with(2, 0, 'someIdField')->andReturnSelf();
4432+
$builder->shouldReceive('forPageBeforeId')->once()->with(2, 1, 'someIdField')->andReturnSelf();
4433+
$builder->shouldReceive('get')->times(2)->andReturn($chunk1, $chunk2);
4434+
4435+
$callbackAssertor = m::mock(stdClass::class);
4436+
$callbackAssertor->shouldReceive('doSomething')->once()->with($chunk1);
4437+
$callbackAssertor->shouldReceive('doSomething')->never()->with($chunk2);
4438+
4439+
$builder->chunkByIdDesc(2, function ($results) use ($callbackAssertor) {
4440+
$callbackAssertor->doSomething($results);
4441+
}, 'someIdField');
4442+
}
4443+
44244444
public function testPaginate()
44254445
{
44264446
$perPage = 16;

0 commit comments

Comments
 (0)