Created
February 18, 2021 11:13
-
-
Save Cartman34/c13e78ecefd0f6c87e68d21ef1b9cac3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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