From a73dc9df13f7d4161a8f962aa40509a10b3ea88d Mon Sep 17 00:00:00 2001 From: Hamid Date: Tue, 26 Mar 2019 23:48:34 +0430 Subject: [PATCH] pageById() and refactor chunkById() --- .../Database/Concerns/BuildsQueries.php | 66 +++++++++++++++++++ src/Illuminate/Database/Eloquent/Builder.php | 44 ++----------- src/Illuminate/Database/Query/Builder.php | 42 ++---------- 3 files changed, 74 insertions(+), 78 deletions(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 1051f2c91c85..2d907f06f5af 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -66,6 +66,72 @@ public function each(callable $callback, $count = 1000) }); } + /** + * Chunk the results of a query by comparing IDs. + * + * @param int $count + * @param callable $callback + * @param string $column + * @param string $alias + * @return bool + */ + public function chunkById($count, callable $callback, $column = null, $alias = null) + { + $column = $column ?: $this->defaultKeyName(); + + $alias = $alias ?: $column; + + $lastId = 0; + + 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 call the callback with the current chunk of these results here. + $results = $clone->forPageAfterId($count, $lastId, $column)->get(); + + $countResults = $results->count(); + + if ($countResults == 0) { + break; + } + + // On each chunk result set, we will pass them to the callback and then let the + // developer take care of everything within the callback, which allows us to + // keep the memory low for spinning through large result sets for working. + if ($callback($results) === false) { + return false; + } + + $lastId = $results->last()->{$alias}; + + unset($results); + } while ($countResults == $count); + + return true; + } + + /** + * Execute a callback over each item while chunking by id. + * + * @param callable $callback + * @param int $count + * @param string $column + * @param string $alias + * @return bool + */ + public function eachById(callable $callback, $count = 1000, $column = null, $alias = null) + { + return $this->chunkById($count, function ($results) use ($callback) { + foreach ($results as $key => $value) { + if ($callback($value, $key) === false) { + return false; + } + } + }, $column, $alias); + } + /** * Execute the query and get the first result. * diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index 60e21e14e838..d838e4f41e02 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -610,49 +610,13 @@ public function cursor() } /** - * Chunk the results of a query by comparing numeric IDs. + * Get the default key name of the table. * - * @param int $count - * @param callable $callback - * @param string $column - * @param string|null $alias - * @return bool + * @return string */ - public function chunkById($count, callable $callback, $column = null, $alias = null) + protected function defaultKeyName() { - $column = is_null($column) ? $this->getModel()->getKeyName() : $column; - - $alias = is_null($alias) ? $column : $alias; - - $lastId = 0; - - 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 call the callback with the current chunk of these results here. - $results = $clone->forPageAfterId($count, $lastId, $column)->get(); - - $countResults = $results->count(); - - if ($countResults == 0) { - break; - } - - // On each chunk result set, we will pass them to the callback and then let the - // developer take care of everything within the callback, which allows us to - // keep the memory low for spinning through large result sets for working. - if ($callback($results) === false) { - return false; - } - - $lastId = $results->last()->{$alias}; - - unset($results); - } while ($countResults == $count); - - return true; + return $this->getModel()->getKeyName(); } /** diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 82f351b1d255..a98f25ed4292 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -1835,47 +1835,13 @@ public function cursor() } /** - * Chunk the results of a query by comparing numeric IDs. + * Get the default key name of the table. * - * @param int $count - * @param callable $callback - * @param string $column - * @param string $alias - * @return bool + * @return string */ - public function chunkById($count, callable $callback, $column = 'id', $alias = null) + protected function defaultKeyName() { - $alias = $alias ?: $column; - - $lastId = 0; - - 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 call the callback with the current chunk of these results here. - $results = $clone->forPageAfterId($count, $lastId, $column)->get(); - - $countResults = $results->count(); - - if ($countResults == 0) { - break; - } - - // On each chunk result set, we will pass them to the callback and then let the - // developer take care of everything within the callback, which allows us to - // keep the memory low for spinning through large result sets for working. - if ($callback($results) === false) { - return false; - } - - $lastId = $results->last()->{$alias}; - - unset($results); - } while ($countResults == $count); - - return true; + return 'id'; } /**