0
votes

I have a very specific case in Laravel framework pagination.

Imagine I get my results from a Redis API by passing offset and limit parameters. In the other words, the paginating stuff is done on the API side. Now when I get the results in my Laravel app I want to show them in a pagination. I mean a simple pagination view that offers a navigation to the other pages. for example, the second page means I have to send a request to my Redis API in order to get the second set of data.

Based on what I understand From Laravel paginator class, it needs a collection of items and gives a convenient pagination over them. Something that is a bit different from what I want.

I need a Class only for making the pagination view which gets a total number of items as a parameter and makes the appropriate links layout.

Is there a convenient way to do this in Laravel? or is implementing it by myself my only option?

1
LengthAwarePaginator more detail in laravel.com/docs/5.6/pagination#displaying-pagination-results under "Manually Creating A Paginator"apokryfos
Thanks for that,I have read that document but that it doesn't do what I need. It gets a collection of items and other options as parameters and do a pagination over themM.Shahrokhi
Could give it a collection of bills of the length you need if you just need the links.apokryfos
what do you mean by a collection of bills? I don't get the idea . do you mean a fake collection? but how?M.Shahrokhi

1 Answers

1
votes

I'm using below class to get data in pagination using data:-

namespace App\Helpers;

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

class LengthAwareOffsetPaginator extends  LengthAwarePaginator implements
Arrayable,
ArrayAccess,
Countable,
IteratorAggregate,
JsonSerializable,
Jsonable
{
    protected $items;

    protected $total;

    protected $total_pages;

    protected $limit;

    protected $offset;

    protected $options;

    /**
     * LengthAwareOffsetPaginator constructor.
     *
     * @param Collection $items
     * @param $total
     * @param $limit
     * @param $offset
     * @param array $options
     */
    public function __construct(Collection $items, $total, $limit, $offset, array $options = [])
    {
        $this->items = $items;

        if ($items->count() > $limit) {
            $this->items = $items->take($limit);
        }

        $this->total = $total;

        $this->limit = $limit;
        $this->offset = $offset;
        $this->options = $options;

        $this->total_pages = ($total/$limit);
    }

    /**
     * Get url of an offset.
     *
     * @param int $offset
     *
     * @return string Url of an offset
     */
    public function url($pageNumber)
    {
        $query = isset($this->options['queryParameter']) ? $this->options['queryParameter'] : [];

        $offset = ($pageNumber - 1) * $this->limit;
        $query = array_merge($query, ['page' => ['limit' => $this->limit, 'offset' => $offset]]);
        $url = isset($this->options['path']) ? $this->options['path'] : '/';

        return $url.'?'.http_build_query($query);
    }

    /**
     * Get last page.
     *
     * @return int Last page
     */
    public function lastPage()
    {
        $totalPages = ceil($this->total / $this->limit);
        return $totalPages;
    }

    /**
     * Get last page offset.
     *
     * @return int Last page offset
     */
    public function totalPages()
    {
        return $this->total_pages;
    }

    /**
     * Get current page.
     *
     * @return int Last page offset
     */
    public function currentPage()
    {
        $pages = (int)ceil($this->offset / $this->limit);

        $currentPage = ($pages + 1);

        return $currentPage;
    }

    public function perPage()
    {
        return $this->limit;
    }

    /**
     * Get last page url.
     *
     * @return string
     */
    public function lastPageUrl()
    {
        $last = $this->lastPage();

        return $this->url($last);
    }

    /**
     * get next page url.
     *
     * @return string
     */
    public function nextPageUrl()
    {
        $nextOffset = $this->offset + $this->limit;

        return ($nextOffset >= $this->total)
            ? null
            : $this->url($nextOffset);
    }

    /**
     * get previous page url.
     *
     * @return string
     */
    public function previousPageUrl()
    {
        if ($this->offset == 0) {
            return null;
        }

        $prevOffset = $this->offset - $this->limit;

        return ($prevOffset < 0)
            ? $this->url($prevOffset + $this->limit - $this->offset)
            : $this->url($prevOffset);
    }

    public function items()
    {
        return $this->items;
    }

    /**
     * get total items.
     *
     * @return int
     */
    public function total()
    {
        return $this->total;
    }

    /**
     * Get the number of items for the current page.
     *
     * @return int
     */
    public function count()
    {
        // return $this->total;
        return $this->items->count();
    }

    /**
     * Get an iterator for the items.
     *
     * @return \ArrayIterator
     */
    public function getIterator()
    {
        return new ArrayIterator($this->items->all());
    }

    /**
     * Determine if the given item exists.
     *
     * @param mixed $key
     *
     * @return bool
     */
    public function offsetExists($key)
    {
        return $this->items->has($key);
    }

    /**
     * Get the item at the given offset.
     *
     * @param mixed $key
     *
     * @return mixed
     */
    public function offsetGet($key)
    {
        return $this->items->get($key);
    }

    /**
     * Set the item at the given offset.
     *
     * @param mixed $key
     * @param mixed $value
     */
    public function offsetSet($key, $value)
    {
        $this->items->put($key, $value);
    }

    /**
     * Unset the item at the given key.
     *
     * @param mixed $key
     */
    public function offsetUnset($key)
    {
        $this->items->forget($key);
    }

    /**
     * Get the instance as an array.
     *
     * @return array
     */
    public function toArray()
    {
        return [
            'first' => $this->url(0),
            'last' => $this->lastPageUrl(),
            'next' => $this->nextPageUrl(),
            'prev' => $this->previousPageUrl(),
            'data' => $this->items->toArray(),
        ];
    }

    /**
     * Convert the object into something JSON serializable.
     *
     * @return array
     */
    public function jsonSerialize()
    {
        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);
    }
}

you need to call this like:

$options['queryParameter'] = [
    'page' => [
        'limit' => 10,
        'offset' => 0
    ],
    'path' => \Illuminate\Pagination\Paginator::resolveCurrentPath()
];
$result = new LengthAwareOffsetPaginator(
    collect($data),
    $totalItemsCount,
    $this->limit,
    $this->offset,
    $options
);

This will give you following output:

{
  "data": [
    {
        ....
    },
    {
        ....
    }
  ],
  "meta": {
    "pagination": {
      "total": 110,
      "count": 10,
      "per_page": 10,
      "current_page": 1,
      "total_pages": 11,
      "links": [
           "self": "url/pages?page=1",
           "next": "url/pages?page=2",
           "first": "url/pages?page=1",
           "last": "url/pages?page=11"
      ]
    }
  }
}

I think this will help you.