Skip to content

Commit e6a8204

Browse files
committed
Allow paginate with WHERE and ORDER BY clauses
1 parent ef72559 commit e6a8204

File tree

2 files changed

+91
-13
lines changed

2 files changed

+91
-13
lines changed

src/Model.php

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -469,24 +469,53 @@ protected function sanitizePageNumber(int $number) : int
469469
*
470470
* @param mixed $page The current page
471471
* @param mixed $perPage Items per page
472+
* @param array<string>|string $orderBy Order by columns
473+
* @param string $orderByDirection asc or desc
474+
* @param array<array<mixed>> $where Array in this format: `[['id', '=', 25]]`
475+
*
476+
* @see Where
472477
*
473478
* @return array<int,array<mixed>|Entity|stdClass>
474479
*/
475-
public function paginate(mixed $page, mixed $perPage = 10) : array
476-
{
480+
public function paginate(
481+
mixed $page,
482+
mixed $perPage = 10,
483+
array $where = [],
484+
array | string $orderBy = null,
485+
string $orderByDirection = 'asc',
486+
) : array {
477487
$page = Pager::sanitize($page);
478488
$perPage = Pager::sanitize($perPage);
479-
$data = $this->getDatabaseToRead()
489+
$select = $this->getDatabaseToRead()
480490
->select()
481491
->from($this->getTable())
482-
->limit(...$this->makePageLimitAndOffset($page, $perPage))
483-
->run()
484-
->fetchArrayAll();
492+
->limit(...$this->makePageLimitAndOffset($page, $perPage));
493+
if ($where) {
494+
foreach ($where as $args) {
495+
$select->where(...$args);
496+
}
497+
}
498+
if ($orderBy !== null) {
499+
$orderBy = (array) $orderBy;
500+
$orderByDir = \strtolower($orderByDirection);
501+
if ( ! \in_array($orderByDir, [
502+
'asc',
503+
'desc',
504+
])) {
505+
throw new InvalidArgumentException(
506+
'Invalid ORDER BY direction: ' . $orderByDirection
507+
);
508+
}
509+
$orderByDir === 'asc'
510+
? $select->orderByAsc(...$orderBy)
511+
: $select->orderByDesc(...$orderBy);
512+
}
513+
$data = $select->run()->fetchArrayAll();
485514
foreach ($data as &$row) {
486515
$row = $this->makeEntity($row);
487516
}
488517
unset($row);
489-
$this->setPager(new Pager($page, $perPage, $this->count()));
518+
$this->setPager(new Pager($page, $perPage, $this->count($where)));
490519
return $data;
491520
}
492521

tests/ModelTest.php

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,32 +408,81 @@ public function testCount() : void
408408

409409
public function testPaginatedItems() : void
410410
{
411+
$date = \date('Y-m-d H:i:s');
411412
$this->model->returnType = 'array';
412413
self::assertSame([
413414
[
414415
'id' => 1,
415416
'data' => 'foo',
416-
'createdAt' => \date('Y-m-d H:i:s'),
417-
'updatedAt' => \date('Y-m-d H:i:s'),
417+
'createdAt' => $date,
418+
'updatedAt' => $date,
418419
],
419420
], $this->model->paginate(-1, 1));
420421
self::assertSame([
421422
[
422423
'id' => 1,
423424
'data' => 'foo',
424-
'createdAt' => \date('Y-m-d H:i:s'),
425-
'updatedAt' => \date('Y-m-d H:i:s'),
425+
'createdAt' => $date,
426+
'updatedAt' => $date,
426427
],
427428
], $this->model->paginate(1, 1));
428429
self::assertSame([
429430
[
430431
'id' => 2,
431432
'data' => 'bar',
432-
'createdAt' => \date('Y-m-d H:i:s'),
433-
'updatedAt' => \date('Y-m-d H:i:s'),
433+
'createdAt' => $date,
434+
'updatedAt' => $date,
434435
],
435436
], $this->model->paginate(2, 1));
436437
self::assertSame([], $this->model->paginate(3, 1));
438+
self::assertSame([
439+
[
440+
'id' => 2,
441+
'data' => 'bar',
442+
'createdAt' => $date,
443+
'updatedAt' => $date,
444+
],
445+
], $this->model->paginate(1, 10, [
446+
['id', '=', 2],
447+
['id', 'between', 0, 3],
448+
]));
449+
self::assertSame([
450+
[
451+
'id' => 1,
452+
'data' => 'foo',
453+
'createdAt' => $date,
454+
'updatedAt' => $date,
455+
],
456+
[
457+
'id' => 2,
458+
'data' => 'bar',
459+
'createdAt' => $date,
460+
'updatedAt' => $date,
461+
],
462+
], $this->model->paginate(1, 10, [
463+
['id', '>', 0],
464+
['data', 'is not null'],
465+
], 'id'));
466+
self::assertSame([
467+
[
468+
'id' => 2,
469+
'data' => 'bar',
470+
'createdAt' => $date,
471+
'updatedAt' => $date,
472+
],
473+
[
474+
'id' => 1,
475+
'data' => 'foo',
476+
'createdAt' => $date,
477+
'updatedAt' => $date,
478+
],
479+
], $this->model->paginate(1, 10, [
480+
['id', '>', 0],
481+
['data', 'is not null'],
482+
], 'id', 'desc'));
483+
$this->expectException(\InvalidArgumentException::class);
484+
$this->expectExceptionMessage('Invalid ORDER BY direction: Foo');
485+
$this->model->paginate(1, 10, [], 'id', 'Foo');
437486
}
438487

439488
public function testPaginatedUrl() : void

0 commit comments

Comments
 (0)