Skip to content

Instantly share code, notes, and snippets.

@melyouz
Last active May 26, 2021 09:07
Show Gist options
  • Save melyouz/20ec81ea8d7570e440191571369369e9 to your computer and use it in GitHub Desktop.
Save melyouz/20ec81ea8d7570e440191571369369e9 to your computer and use it in GitHub Desktop.
Simple PHP Pagination Class
Simple PHP Pagination Class
<?php
declare(strict_types=1);
namespace App\Domain\Model;
class Pagination
{
const DEFAULT_ITEMS_PER_PAGE = 30;
const DEFAULT_OFFSET_PAGES = 5;
/** @var array */
private $items;
/** @var int */
private $count;
/** @var int */
private $itemsPerPage;
/** @var int */
private $currentPage;
/** @var int */
private $totalPages;
/** @var int */
private $paginationOffset;
public function __construct(array $items, int $itemsPerPage = self::DEFAULT_ITEMS_PER_PAGE, int $currentPage = 1)
{
$this->items = $items;
$this->count = count($items);
$this->itemsPerPage = $itemsPerPage;
$this->currentPage = $currentPage;
$this->totalPages = (int) ceil($this->count / $this->itemsPerPage);
$this->paginationOffset = ($this->currentPage - 1) * $this->itemsPerPage;
}
public function apply(callable $callback)
{
$pagedItems = $this->paginateItems();
foreach ($pagedItems as $index => $item) {
$this->items[$index] = call_user_func($callback, $item);
}
}
public function getItems(): array
{
return array_values($this->paginateItems());
}
public function getCurrentPage(): int
{
return $this->currentPage;
}
public function hasPreviousPage(): bool
{
return $this->currentPage > 1;
}
public function getPreviousPage(): ?int
{
$previousPage = ($this->hasPreviousPage() ? $this->currentPage - 1 : null);
return $previousPage;
}
public function getPreviousPages(): array
{
if (!$this->hasPreviousPage()) {
return [];
}
$leftPages = $this->currentPage - 1;
$previousPagesCount = ($leftPages >= self::DEFAULT_OFFSET_PAGES ? self::DEFAULT_OFFSET_PAGES : $leftPages);
$previousPages = range($this->getPreviousPage(), $this->currentPage - $previousPagesCount);
asort($previousPages);
return array_values($previousPages);
}
public function hasNextPage(): bool
{
return $this->currentPage < $this->totalPages;
}
public function getNextPage(): ?int
{
$nextPage = ($this->hasNextPage() ? $this->currentPage + 1 : null);
return $nextPage;
}
public function getNextPages(): array
{
if (!$this->hasNextPage()) {
return [];
}
$pendingPages = $this->totalPages - $this->currentPage;
$nextPagesCount = ($pendingPages >= self::DEFAULT_OFFSET_PAGES ? self::DEFAULT_OFFSET_PAGES : $pendingPages);
return range($this->getNextPage(), $this->currentPage + $nextPagesCount);
}
public function getTotalItems(): int
{
return $this->count;
}
public function getItemsPerPage(): int
{
return $this->itemsPerPage;
}
public function getTotalPages(): int
{
return $this->totalPages;
}
private function paginateItems()
{
return array_slice($this->items, $this->paginationOffset, $this->itemsPerPage, true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment