Skip to content

Instantly share code, notes, and snippets.

@n1215
Last active October 16, 2019 14:11
Show Gist options
  • Save n1215/87e295f728c0cc24a310ebb9f42491ff to your computer and use it in GitHub Desktop.
Save n1215/87e295f728c0cc24a310ebb9f42491ff to your computer and use it in GitHub Desktop.
BuildsQueries::lazyChunk()
<?php
// usage
/** @var \Illuminate\Support\LazyCollection<Post> $lazyPosts */
$lazyPosts = Post::query()
->lazyChunk(100)
->tapEach(function (Collection $posts) {
$posts->load('author');
})
->collapse();
/** @var \Illuminate\Support\LazyCollection<Post> $lazyPosts */
$lazyPosts = Post::query()
->with(['author'])
->lazyChunkById(50)
->collapse();
// method impl
trait BuildsQueries
{
/**
* Chunk the results of the query as a lazy collection
*
* @param int $count
* @return \Illuminate\Support\LazyCollection
*/
public function lazyChunk(int $count): LazyCollection
{
return LazyCollection::make(function () use ($count) {
$this->enforceOrderBy();
$page = 1;
do {
// We'll execute the query for the given page and get the results. If there are
// no results we can just break and return from here. When there are results
// we will yield the current chunk of these results here.
$results = $this->forPage($page, $count)->get();
$countResults = $results->count();
if ($countResults == 0) {
break;
}
yield $results;
unset($results);
$page++;
} while ($countResults == $count);
});
}
/**
* Chunk the results of a query as a lazy collection by comparing IDs.
*
* @param int $count
* @param string|null $column
* @param string|null $alias
* @return \Illuminate\Support\LazyCollection
*/
public function lazyChunkById($count, $column = null, $alias = null): LazyCollection
{
return LazyCollection::make(function () use ($column, $alias) {
$column = $column ?? $this->defaultKeyName();
$alias = $alias ?? $column;
$lastId = null;
do {
$clone = clone $this;
// We'll execute the query for the given page and get the results. If there are
// no results we can just break and return from here. When there are results
// we will yield the current chunk of these results here.
$results = $clone->forPageAfterId($count, $lastId, $column)->get();
$countResults = $results->count();
if ($countResults == 0) {
break;
}
yield $results;
$lastId = $results->last()->{$alias};
unset($results);
} while ($countResults == $count);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment