Skip to content

Instantly share code, notes, and snippets.

@neoascetic
Last active November 27, 2017 20:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neoascetic/5027772 to your computer and use it in GitHub Desktop.
Save neoascetic/5027772 to your computer and use it in GitHub Desktop.
[Laravel] Lazy Paginator for Laravel
<?php
/**
* Lazy Paginator for Laravel
* Does not use number of pages, simply shows First, Previous and Next links
*
* Usage:
* $pager = LazyPaginator(
* Model::where_field($field), // Eloquent, Fluent Query or array of objects
* Model::$per_page,
* ['columns', 'to', 'fetch']) // will be used if first argument is a Query
*
* To have correct translation of text for First link,
* simply add 'first' key with your text to 'application/language/{lang}/pagination.php'
*
*/
class LazyPaginator {
/**
* The results for the current page
*
* @var array
*/
public $results;
/**
* The current page
*
* @var int
*/
public $page;
/**
* The number of items per page
*
* @var int
*/
public $per_page;
/**
* Does next page exist
*
* @var bool
*/
protected $next_page_exists;
/**
* The values that should be appended to the end of the link query strings
*
* @var array
*/
protected $appends;
/**
* The compiled appendage that will be appended to the links
* This consists of a sprintf format with a page place-holder and query string
*
* @var string
*/
protected $appendage;
/**
* The language that should be used when creating the pagination links
*
* @var string
*/
protected $language;
/**
* Create a new LazyPaginator instance
*
* @param array $results
* @param int $page
* @return void
*/
protected function __construct($results, $page, $per_page, $next_page_exists) {
$this->page = $page;
$this->results = $results;
$this->per_page = $per_page;
$this->next_page_exists = $next_page_exists;
}
/**
* Create a new LazyPaginator instance
*
* @param array|Query $results
* @param int $per_page
* @param array $columns
* @param bool $next_page_exists
* @return LazyPaginator
*/
public static function make($results, $per_page = 20, $columns = array('*'), $next_page_exists = null) {
$page = static::page();
if ($results instanceof \Laravel\Database\Query || $results instanceof \Laravel\Database\Eloquent\Query) {
$results = $results->skip(($page - 1) * $per_page)->take($per_page + 1)->get($columns);
if (count($results) === $per_page + 1) {
$next_page_exists = true;
array_pop($results);
} else {
$next_page_exists = false;
}
} else if (is_null($next_page_exists)) {
$next_page_exists = count($results) === $per_page;
}
return new static($results, $page, $per_page, $next_page_exists);
}
/**
* Get the current page from the request query string
*
* @return int
*/
public static function page() {
$page = Input::get('page', 1);
return (static::valid($page)) ? $page : 1;
}
/**
* Determine if a given page number is a valid page
* A valid page must be greater than or equal to one and a valid integer
*
* @param int $page
* @return bool
*/
protected static function valid($page) {
return $page >= 1 and filter_var($page, FILTER_VALIDATE_INT) !== false;
}
/**
* Create the HTML pagination links
*
* @return string
*/
public function links() {
$content = '<ul>' . $this->first() . $this->previous() . $this->disabled_link('page', $this->page) . $this->next() . '</ul>';
return '<div class="pagination">'.$content.'</div>';
}
/**
* Generate the "first" HTML link
* @param string $text
* @return bool
*/
public function first($text = null) {
$disabled = $this->page <= 1;
return $this->element(__FUNCTION__, 1, $text, $disabled);
}
/**
* Generate the "previous" HTML link
* @param string $text
* @return bool
*/
public function previous($text = null) {
$disabled = $this->page <= 1;
return $this->element(__FUNCTION__, $this->page - 1, $text, $disabled);
}
/**
* Generate the "next" HTML link
*
* @param string $text
* @return string
*/
public function next($text = null) {
$disabled = !$this->next_page_exists;
return $this->element(__FUNCTION__, $this->page + 1, $text, $disabled);
}
/**
* Create a chronological pagination element, such as a "first", "previous" or "next" link
*
* @param string $element
* @param int $page
* @param string $text
* @param bool $disabled
* @return string
*/
protected function element($element, $page, $text, $disabled) {
$class = "{$element}_page";
if (is_null($text)) {
$text = Lang::line("pagination.{$element}")->get($this->language);
}
if ($disabled) return $this->disabled_link($class, $text);
return $this->link($page, $text, $class);
}
/**
* Create a disabled HTML page link
*
* @param string $class
* @param string $text
* @return string
*/
protected function disabled_link($class, $text) {
return '<li'.HTML::attributes(array('class'=>"{$class} disabled")).'><a href="#">'.$text.'</a></li>';
}
/**
* Create a HTML page link
*
* @param int $page
* @param string $text
* @param string $class
* @return string
*/
protected function link($page, $text, $class) {
$query = '?page='.$page.$this->appendage($this->appends);
return '<li'.HTML::attributes(array('class' => $class)).'>'.HTML::link(URI::current().$query, $text, array(), Request::secure()).'</li>';
}
/**
* Create the "appendage" to be attached to every pagination link
*
* @param array $appends
* @return string
*/
protected function appendage($appends) {
if (!is_null($this->appendage)) return $this->appendage;
if(count($appends) <= 0) {
return $this->appendage = '';
}
return $this->appendage = '&'.http_build_query($appends);
}
/**
* Set the items that should be appended to the link query strings
*
* @param array $values
* @return LazyPaginator
*/
public function appends($values) {
$this->appends = $values;
return $this;
}
/**
* Set the language that should be used when creating the pagination links
*
* @param array $language
* @return LazyPaginator
*/
public function speaks($language) {
$this->language = $language;
return $this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment