i have a pagination library in php. i want to know:
- how can i make it more efficient when passing large arrays into the constructor
- how can i add db support
paginator.php
public function __construct($options = [])
{
$this->items = $options['data'];
$this->limit = $options['limit'] ?? 10;
$this->currentPage = $options['currentPage'] ?? 1;
//$this->urlPattern = $options['urlPattern'];
$this->updateNumPages();
}
public function paginate(int $page = 1): PaginatorInterface
{
if ($page <= 0 || $this->limit <= 0) {
throw new \LogicException("Invalid parameters.");
}
$offset = ($page - 1) * $this->limit;
$pagination = new DefaultPaginator();
$items = new Collection($this->items, $offset, $this->limit);
if ($this->items instanceof \ArrayObject || is_array($this->items)) {
$data = new ArrayData();
$data->fetchItems($items);
} else {
throw new \RuntimeException("Data type not supported for pagination.");
}
$pagination->setCurrentPageNumber($page);
$pagination->setNumberOfPages((int) ceil($items->getCount() / $items->getLimit()));
$pagination->setItems($items->getItems());
$pagination->setTotal($items->getCount());
$pagination->setTotalOnCurrentPage(count($items->getItems()));
$pagination->setTotalPerPage($this->limit);
return $pagination;
}
my repository is here https://github.com/shorif2000/pagination
here is where i am slicing the array.
class ArrayData implements DataInterface
{
public function fetchItems(Collection &$items): void
{
if (is_array($items->getCollection())) {
$items->setItems(array_slice(
$items->getCollection(),
$items->getOffset(),
$items->getLimit()
));
$items->setCount(count($items->getCollection()));
} elseif ($items->getCollection() instanceof ArrayObject) {
$collection = $items->getCollection();
$items->setItems(new ArrayObject(array_slice(
$collection->getArrayCopy(),
$items->getOffset(),
$items->getLimit()
)));
$items->setCount($collection->count());
}
}
}
UPDATE
I created this class to add support for db or array/ArrayObject
class Pagination
{
public function __construct($options = [], $mode = 'Default')
{
eval('$this = Pagination::factory($options, $mode);');
}
public static function &factory($options, $mode)
{
$classname = ($mode == 'Default') ? 'Pagination\\Paginator' : 'Pagination\\DbPage' ;
// If the class exists, return a new instance of it.
if (class_exists($classname)) {
$pagination = new $classname($options);
return $pagination;
}
$null = null;
return $null;
}
}
UPDATE
with the answer to test i have the following
$pageNumber = 1;
$itemsPerPage = 10;
$input = range(0, 100);
$input = array_slice($input, 0, 10);
$total = count($input);
print_r((new PaginatorFactory(new ArrayPageProvider($input)))->createPaginator($pageNumber, $itemsPerPage));