From 6bb40b61bf4f2f945e1af5c46b89cbe9e426570f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= Date: Wed, 2 Sep 2020 16:34:30 +0800 Subject: [PATCH] Added method `Hyperf\Database\Query\Builder::forPageBeforeId` (#2411) --- CHANGELOG-2.0.md | 4 + src/database/src/Query/Builder.php | 23 ++++- src/database/tests/ModelRealBuilderTest.php | 96 +++++++++++++++++++++ 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 src/database/tests/ModelRealBuilderTest.php diff --git a/CHANGELOG-2.0.md b/CHANGELOG-2.0.md index 39deab2597..eaf28f85e8 100644 --- a/CHANGELOG-2.0.md +++ b/CHANGELOG-2.0.md @@ -1,5 +1,9 @@ # v2.0.10 - TBD +## Added + +- [#2411](https://github.com/hyperf/hyperf/pull/2411) Added method `Hyperf\Database\Query\Builder::forPageBeforeId` for database. + # v2.0.9 - 2020-08-31 ## Added diff --git a/src/database/src/Query/Builder.php b/src/database/src/Query/Builder.php index bea6c54eec..5ac5438b5f 100755 --- a/src/database/src/Query/Builder.php +++ b/src/database/src/Query/Builder.php @@ -1705,13 +1705,32 @@ public function forPage($page, $perPage = 15) return $this->skip(($page - 1) * $perPage)->take($perPage); } + /** + * Constrain the query to the previous "page" of results before a given ID. + * + * @param int $perPage + * @param null|int $lastId + * @param string $column + * @return $this + */ + public function forPageBeforeId($perPage = 15, $lastId = 0, $column = 'id') + { + $this->orders = $this->removeExistingOrdersFor($column); + + if (! is_null($lastId)) { + $this->where($column, '<', $lastId); + } + + return $this->orderBy($column, 'desc')->limit($perPage); + } + /** * Constrain the query to the next "page" of results after a given ID. * * @param int $perPage * @param null|int $lastId * @param string $column - * @return \Hyperf\Database\Query\Builder|static + * @return $this */ public function forPageAfterId($perPage = 15, $lastId = 0, $column = 'id') { @@ -1721,7 +1740,7 @@ public function forPageAfterId($perPage = 15, $lastId = 0, $column = 'id') $this->where($column, '>', $lastId); } - return $this->orderBy($column, 'asc')->take($perPage); + return $this->orderBy($column, 'asc')->limit($perPage); } /** diff --git a/src/database/tests/ModelRealBuilderTest.php b/src/database/tests/ModelRealBuilderTest.php new file mode 100644 index 0000000000..808f9135db --- /dev/null +++ b/src/database/tests/ModelRealBuilderTest.php @@ -0,0 +1,96 @@ +channel = new Channel(999); + } + + protected function tearDown() + { + Mockery::close(); + } + + public function testForPageBeforeId() + { + $this->getContainer(); + + User::query()->forPageBeforeId(2)->get(); + User::query()->forPageBeforeId(2, null)->get(); + User::query()->forPageBeforeId(2, 1)->get(); + + $sqls = [ + ['select * from `user` where `id` < ? order by `id` desc limit 2', [0]], + ['select * from `user` order by `id` desc limit 2', []], + ['select * from `user` where `id` < ? order by `id` desc limit 2', [1]], + ]; + while ($event = $this->channel->pop(0.001)) { + if ($event instanceof QueryExecuted) { + $this->assertSame([$event->sql, $event->bindings], array_shift($sqls)); + } + } + } + + public function testForPageAfterId() + { + $this->getContainer(); + + User::query()->forPageAfterId(2)->get(); + User::query()->forPageAfterId(2, null)->get(); + User::query()->forPageAfterId(2, 1)->get(); + + $sqls = [ + ['select * from `user` where `id` > ? order by `id` asc limit 2', [0]], + ['select * from `user` order by `id` asc limit 2', []], + ['select * from `user` where `id` > ? order by `id` asc limit 2', [1]], + ]; + while ($event = $this->channel->pop(0.001)) { + if ($event instanceof QueryExecuted) { + $this->assertSame([$event->sql, $event->bindings], array_shift($sqls)); + } + } + } + + protected function getContainer() + { + $dispatcher = Mockery::mock(EventDispatcherInterface::class); + $dispatcher->shouldReceive('dispatch')->with(Mockery::any())->andReturnUsing(function ($event) { + $this->channel->push($event); + }); + $container = ContainerStub::getContainer(function ($conn) use ($dispatcher) { + $conn->setEventDispatcher($dispatcher); + }); + $container->shouldReceive('get')->with(EventDispatcherInterface::class)->andReturn($dispatcher); + + return $container; + } +}