master

laravel/framework

Last updated at: 29/12/2023 09:23

LengthAwarePaginator.php

TLDR

The LengthAwarePaginator.php file in the Illuminate\Pagination namespace contains the LengthAwarePaginator class, which is an implementation of LengthAwarePaginatorContract. This class is responsible for creating and rendering pagination links for a collection of items. It determines the total number of items, the last available page, and provides methods to retrieve information about the pagination, such as the current page, the next and previous page URLs, and the total number of items. It also includes methods to render the paginator using a view, retrieve the paginator links as a collection, and convert the paginator to an array or JSON representation.

Methods

__construct

Creates a new paginator instance.

  • Parameters:
    • $items: The collection of items to paginate.
    • $total: The total number of items before slicing.
    • $perPage: The number of items per page.
    • $currentPage: The current page number (optional).
    • $options: An array of options including the path, query, fragment, and page name (optional).

setCurrentPage

Get the current page for the request.

  • Parameters:
    • $currentPage: The current page number.
    • $pageName: The name of the page parameter (e.g. "page").
  • Returns: The validated current page number.

links

Render the paginator using the given view.

  • Parameters:
    • $view: The view to render (optional).
    • $data: Additional data to pass to the view (optional).
  • Returns: An instance of Illuminate\Contracts\Support\Htmlable representing the rendered pagination links.

render

Render the paginator using the given view.

  • Parameters:
    • $view: The view to render (optional).
    • $data: Additional data to pass to the view (optional).
  • Returns: An instance of Illuminate\Contracts\Support\Htmlable representing the rendered paginator.

linkCollection

Get the paginator links as a collection (for JSON responses).

  • Returns: An instance of Illuminate\Support\Collection containing the paginator links.

elements

Get the array of elements to pass to the view.

  • Returns: An array of elements representing the pagination.

total

Get the total number of items being paginated.

  • Returns: The total number of items.

hasMorePages

Determine if there are more items in the data source.

  • Returns: true if there are more pages, false otherwise.

nextPageUrl

Get the URL for the next page.

  • Returns: The URL for the next page, or null if there is no next page.

lastPage

Get the last page number.

  • Returns: The last page number.

toArray

Get the instance as an array.

  • Returns: An array representing the instance.

jsonSerialize

Convert the object into something JSON serializable.

  • Returns: An array representing the instance.

toJson

Convert the object to its JSON representation.

  • Parameters:
    • $options: JSON encoding options (optional).
  • Returns: The JSON representation of the instance.
<?php

namespace Illuminate\Pagination;

use ArrayAccess;
use Countable;
use Illuminate\Contracts\Pagination\LengthAwarePaginator as LengthAwarePaginatorContract;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Collection;
use IteratorAggregate;
use JsonSerializable;

class LengthAwarePaginator extends AbstractPaginator implements Arrayable, ArrayAccess, Countable, IteratorAggregate, Jsonable, JsonSerializable, LengthAwarePaginatorContract
{
    /**
     * The total number of items before slicing.
     *
     * @var int
     */
    protected $total;

    /**
     * The last available page.
     *
     * @var int
     */
    protected $lastPage;

    /**
     * Create a new paginator instance.
     *
     * @param  mixed  $items
     * @param  int  $total
     * @param  int  $perPage
     * @param  int|null  $currentPage
     * @param  array  $options  (path, query, fragment, pageName)
     * @return void
     */
    public function __construct($items, $total, $perPage, $currentPage = null, array $options = [])
    {
        $this->options = $options;

        foreach ($options as $key => $value) {
            $this->{$key} = $value;
        }

        $this->total = $total;
        $this->perPage = (int) $perPage;
        $this->lastPage = max((int) ceil($total / $perPage), 1);
        $this->path = $this->path !== '/' ? rtrim($this->path, '/') : $this->path;
        $this->currentPage = $this->setCurrentPage($currentPage, $this->pageName);
        $this->items = $items instanceof Collection ? $items : Collection::make($items);
    }

    /**
     * Get the current page for the request.
     *
     * @param  int  $currentPage
     * @param  string  $pageName
     * @return int
     */
    protected function setCurrentPage($currentPage, $pageName)
    {
        $currentPage = $currentPage ?: static::resolveCurrentPage($pageName);

        return $this->isValidPageNumber($currentPage) ? (int) $currentPage : 1;
    }

    /**
     * Render the paginator using the given view.
     *
     * @param  string|null  $view
     * @param  array  $data
     * @return \Illuminate\Contracts\Support\Htmlable
     */
    public function links($view = null, $data = [])
    {
        return $this->render($view, $data);
    }

    /**
     * Render the paginator using the given view.
     *
     * @param  string|null  $view
     * @param  array  $data
     * @return \Illuminate\Contracts\Support\Htmlable
     */
    public function render($view = null, $data = [])
    {
        return static::viewFactory()->make($view ?: static::$defaultView, array_merge($data, [
            'paginator' => $this,
            'elements' => $this->elements(),
        ]));
    }

    /**
     * Get the paginator links as a collection (for JSON responses).
     *
     * @return \Illuminate\Support\Collection
     */
    public function linkCollection()
    {
        return collect($this->elements())->flatMap(function ($item) {
            if (! is_array($item)) {
                return [['url' => null, 'label' => '...', 'active' => false]];
            }

            return collect($item)->map(function ($url, $page) {
                return [
                    'url' => $url,
                    'label' => (string) $page,
                    'active' => $this->currentPage() === $page,
                ];
            });
        })->prepend([
            'url' => $this->previousPageUrl(),
            'label' => function_exists('__') ? __('pagination.previous') : 'Previous',
            'active' => false,
        ])->push([
            'url' => $this->nextPageUrl(),
            'label' => function_exists('__') ? __('pagination.next') : 'Next',
            'active' => false,
        ]);
    }

    /**
     * Get the array of elements to pass to the view.
     *
     * @return array
     */
    protected function elements()
    {
        $window = UrlWindow::make($this);

        return array_filter([
            $window['first'],
            is_array($window['slider']) ? '...' : null,
            $window['slider'],
            is_array($window['last']) ? '...' : null,
            $window['last'],
        ]);
    }

    /**
     * Get the total number of items being paginated.
     *
     * @return int
     */
    public function total()
    {
        return $this->total;
    }

    /**
     * Determine if there are more items in the data source.
     *
     * @return bool
     */
    public function hasMorePages()
    {
        return $this->currentPage() < $this->lastPage();
    }

    /**
     * Get the URL for the next page.
     *
     * @return string|null
     */
    public function nextPageUrl()
    {
        if ($this->hasMorePages()) {
            return $this->url($this->currentPage() + 1);
        }
    }

    /**
     * Get the last page.
     *
     * @return int
     */
    public function lastPage()
    {
        return $this->lastPage;
    }

    /**
     * Get the instance as an array.
     *
     * @return array
     */
    public function toArray()
    {
        return [
            'current_page' => $this->currentPage(),
            'data' => $this->items->toArray(),
            'first_page_url' => $this->url(1),
            'from' => $this->firstItem(),
            'last_page' => $this->lastPage(),
            'last_page_url' => $this->url($this->lastPage()),
            'links' => $this->linkCollection()->toArray(),
            'next_page_url' => $this->nextPageUrl(),
            'path' => $this->path(),
            'per_page' => $this->perPage(),
            'prev_page_url' => $this->previousPageUrl(),
            'to' => $this->lastItem(),
            'total' => $this->total(),
        ];
    }

    /**
     * Convert the object into something JSON serializable.
     *
     * @return array
     */
    public function jsonSerialize(): array
    {
        return $this->toArray();
    }

    /**
     * Convert the object to its JSON representation.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0)
    {
        return json_encode($this->jsonSerialize(), $options);
    }
}