lampager/lampager-laravel

Rapid pagination for Laravel

v0.5.2 2023-03-15 07:56 UTC

This package is auto-updated.

Last update: 2024-10-15 11:14:45 UTC


README

lampager-laravel

Build Status Coverage Status Scrutinizer Code Quality

Lampager for Laravel

Rapid pagination without using OFFSET

Requirements

Installing

composer require lampager/lampager-laravel

Basic Usage

Register service provider.

config/app.php:

        /*
         * Package Service Providers...
         */
        Lampager\Laravel\MacroServiceProvider::class,

Then you can chain ->lampager() method from Query Builder, Eloquent Builder and Relation.

$cursor = [
    'id' => 3,
    'created_at' => '2017-01-10 00:00:00',
    'updated_at' => '2017-01-20 00:00:00',
];

$result = App\Post::whereUserId(1)
    ->lampager()
    ->forward()
    ->limit(5)
    ->orderByDesc('updated_at') // ORDER BY `updated_at` DESC, `created_at` DESC, `id` DESC
    ->orderByDesc('created_at')
    ->orderByDesc('id')
    ->seekable()
    ->paginate($cursor)
    ->toJson(JSON_PRETTY_PRINT);

It will run the optimized query.

(

    SELECT * FROM `posts`
    WHERE `user_id` = 1
    AND (
        `updated_at` = '2017-01-20 00:00:00' AND `created_at` = '2017-01-10 00:00:00' AND `id` > 3
        OR
        `updated_at` = '2017-01-20 00:00:00' AND `created_at` > '2017-01-10 00:00:00'
        OR
        `updated_at` > '2017-01-20 00:00:00'
    )
    ORDER BY `updated_at` ASC, `created_at` ASC, `id` ASC
    LIMIT 1

) UNION ALL (

    SELECT * FROM `posts`
    WHERE `user_id` = 1
    AND (
        `updated_at` = '2017-01-20 00:00:00' AND `created_at` = '2017-01-10 00:00:00' AND `id` <= 3
        OR
        `updated_at` = '2017-01-20 00:00:00' AND `created_at` < '2017-01-10 00:00:00'
        OR
        `updated_at` < '2017-01-20 00:00:00'
    )
    ORDER BY `updated_at` DESC, `created_at` DESC, `id` DESC
    LIMIT 6

)

And you'll get

{
  "records": [
    {
      "id": 3,
      "user_id": 1,
      "text": "foo",
      "created_at": "2017-01-10 00:00:00",
      "updated_at": "2017-01-20 00:00:00"
    },
    {
      "id": 5,
      "user_id": 1,
      "text": "bar",
      "created_at": "2017-01-05 00:00:00",
      "updated_at": "2017-01-20 00:00:00"
    },
    {
      "id": 4,
      "user_id": 1,
      "text": "baz",
      "created_at": "2017-01-05 00:00:00",
      "updated_at": "2017-01-20 00:00:00"
    },
    {
      "id": 2,
      "user_id": 1,
      "text": "qux",
      "created_at": "2017-01-17 00:00:00",
      "updated_at": "2017-01-18 00:00:00"
    },
    {
      "id": 1,
      "user_id": 1,
      "text": "quux",
      "created_at": "2017-01-16 00:00:00",
      "updated_at": "2017-01-18 00:00:00"
    }
  ],
  "has_previous": false,
  "previous_cursor": null,
  "has_next": true,
  "next_cursor": {
    "updated_at": "2017-01-18 00:00:00",
    "created_at": "2017-01-14 00:00:00",
    "id": 6
  }
}

Resource Collection

Lampager supports Laravel's API Resources.

Use helper traits on Resource and ResourceCollection.

use Illuminate\Http\Resources\Json\JsonResource;
use Lampager\Laravel\LampagerResourceTrait;

class PostResource extends JsonResource
{
    use LampagerResourceTrait;
}
use Illuminate\Http\Resources\Json\ResourceCollection;
use Lampager\Laravel\LampagerResourceCollectionTrait;

class PostResourceCollection extends ResourceCollection
{
    use LampagerResourceCollectionTrait;
}
$posts = App\Post::lampager()
    ->orderByDesc('id')
    ->paginate();

return new PostResourceCollection($posts);
{
  "data": [/* ... */],
  "has_previous": false,
  "previous_cursor": null,
  "has_next": true,
  "next_cursor": {/* ... */}
}

Classes

Note: See also lampager/lampager.

Paginator, Processor and PaginationResult are macroable.

API

Note: See also lampager/lampager.

Paginator::__construct()
Paginator::create()

Create a new paginator instance.
If you use Laravel macros, however, you don't need to directly instantiate.

static Paginator create(QueryBuilder|EloquentBuilder|Relation $builder): static
Paginator::__construct(QueryBuilder|EloquentBuilder|Relation $builder)
  • QueryBuilder means \Illuminate\Database\Query\Builder
  • EloquentBuilder means \Illuminate\Database\Eloquent\Builder
  • Relation means \Illuminate\Database\Eloquent\Relation

Paginator::transform()

Transform Lampager Query into Illuminate builder.

Paginator::transform(Query $query): QueryBuilder|EloquentBuilder|Relation

Paginator::build()

Perform configure + transform.

Paginator::build(\Lampager\Contracts\Cursor|array $cursor = []): QueryBuilder|EloquentBuilder|Relation

Paginator::paginate()

Perform configure + transform + process.

Paginator::paginate(\Lampager\Contracts\Cursor|array $cursor = []): \Lampager\Laravel\PaginationResult

Arguments

  • (mixed) $cursor
    An associative array that contains $column => $value or an object that implements \Lampager\Contracts\Cursor. It must be all-or-nothing.
    • For initial page, omit this parameter or pass empty array.
    • For subsequent pages, pass all parameters. Partial parameters are not allowd.

Return Value

e.g.

(Default format when using \Illuminate\Database\Eloquent\Builder)

object(Lampager\Laravel\PaginationResult)#1 (5) {
  ["records"]=>
  object(Illuminate\Database\Eloquent\Collection)#2 (1) {
    ["items":protected]=>
    array(5) {
      [0]=>
      object(App\Post)#2 (26) { ... }
      [1]=>
      object(App\Post)#3 (26) { ... }
      [2]=>
      object(App\Post)#4 (26) { ... }
      [3]=>
      object(App\Post)#5 (26) { ... }
      [4]=>
      object(App\Post)#6 (26) { ... }
    }
  }
  ["hasPrevious"]=>
  bool(false)
  ["previousCursor"]=>
  NULL
  ["hasNext"]=>
  bool(true)
  ["nextCursor"]=>
  array(2) {
    ["updated_at"]=>
    string(19) "2017-01-18 00:00:00"
    ["created_at"]=>
    string(19) "2017-01-14 00:00:00"
    ["id"]=>
    int(6)
  }
}

Paginator::useFormatter()
Paginator::restoreFormatter()
Paginator::process()

Invoke Processor methods.

Paginator::useFormatter(Formatter|callable $formatter): $this
Paginator::restoreFormatter(): $this
Paginator::process(\Lampager\Query $query, \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Collection $rows): \Lampager\Laravel\PaginationResult

PaginationResult::toArray()
PaginationResult::jsonSerialize()

Convert the object into array.

IMPORTANT: camelCase properties are converted into snake_case form.

PaginationResult::toArray(): array
PaginationResult::jsonSerialize(): array

PaginationResult::__call()

Call macro or Collection methods.

PaginationResult::__call(string $name, array $args): mixed

e.g.

PaginationResult::macro('foo', function () {
    return ...;
});
$foo = $result->foo();
$first = $result->first();