Skip to content

Instantly share code, notes, and snippets.

@Cartman34
Created February 18, 2021 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cartman34/c13e78ecefd0f6c87e68d21ef1b9cac3 to your computer and use it in GitHub Desktop.
Save Cartman34/c13e78ecefd0f6c87e68d21ef1b9cac3 to your computer and use it in GitHub Desktop.
<?php
/**
* @author Florent HAZARD <f.hazard@sowapps.com>
*
* Paginate results from Doctrine QueryBuilder
*/
namespace App\Core\Entity;
use ArrayIterator;
use Doctrine\ORM\QueryBuilder;
use Iterator;
use OutOfBoundsException;
class PaginatedResult {
protected Iterator $results;
protected int $page;
protected int $resultPerPage;
protected int $count;
protected int $pageDelta = 2;
/**
* PaginatedResult constructor
*
* @param Iterator $results
* @param int $page
* @param int $resultPerPage
* @param int $count
*/
public function __construct(Iterator $results, int $page, int $resultPerPage, int $count) {
$this->results = $results;
$this->page = $page;
$this->resultPerPage = $resultPerPage;
$this->count = $count;
if( $page > $this->getPageCount() ) {
throw new OutOfBoundsException('Wrong page number');
}
}
/**
* @return bool
*/
public function hasResults(): bool {
return !!$this->count;
}
/**
* @return int
*/
public function getPageCount(): int {
return max(ceil($this->count / $this->resultPerPage), 1);
}
/**
* @return Iterator
*/
public function getResults(): Iterator {
return $this->results;
}
/**
* @return mixed|array
*/
public function getNext() {
$results = $this->getResults();
$results->next();
return $results->current();
}
/**
* @return int
*/
public function getPage(): int {
return $this->page;
}
/**
* @return int
*/
public function getResultPerPage(): int {
return $this->resultPerPage;
}
/**
* @return int
*/
public function getCount(): int {
return $this->count;
}
/**
* @return bool
*/
public function hasPreviousPage(): bool {
return !$this->isFirstPage();
}
/**
* @return int
*/
public function isFirstPage(): int {
return $this->page === 1;
}
/**
* @return bool
*/
public function hasNextPage(): bool {
return !$this->isLastPage();
}
/**
* @return int
*/
public function isLastPage(): int {
return $this->page === $this->getPageCount();
}
/**
* @return int
*/
public function getDeltaStart(): int {
return (int) max($this->page - $this->pageDelta, 1);
}
/**
* @return int
*/
public function getDeltaEnd() {
return (int) min($this->page + $this->pageDelta, $this->getPageCount());
}
public static function paginate(QueryBuilder $queryBuilder, int $page, int $resultPerPage, string $alias) {
$counter = clone $queryBuilder;
if( $page < 1 ) {
throw new OutOfBoundsException('Wrong page number');
}
$counter->select('COUNT(' . $alias . '.id)');
$count = $counter->getQuery()
->getSingleScalarResult();
$resultMax = $page * $resultPerPage;
$resultMin = $resultMax - $resultPerPage;
if( ($count - 1) >= $resultMin ) {
$results = $queryBuilder
->setMaxResults($resultPerPage)
->setFirstResult($resultMin)
->getQuery()
->iterate();
} else {
$results = new ArrayIterator();
}
return new PaginatedResult($results, $page, $resultPerPage, $count);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment