Lampager: Rapid Pagination for Various PHP Frameworks

Lampager Core

The core package of Lampager

Requirements

  • PHP: ^5.6 || ^7.0 || ^8.0

Installing

composer require lampager/lampager

Usage

Basically you don't need to directly use this package. For example, if you use Laravel, install lampager/lampager-laravel.

However, you can manually use like this:

use Lampager\Paginator;
use Lampager\ArrayProcessor;

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

$query = (new Paginator())
    ->forward()
    ->limit(5)
    ->orderByDesc('updated_at') // ORDER BY `updated_at` DESC, `created_at` DESC, `id` DESC
    ->orderByDesc('created_at')
    ->orderByDesc('id')
    ->seekable()
    ->configure($cursor);

$rows = run_your_query_using_PDO($query); // Note: SQLite3 driver example is bundled in the tests/StubPaginator.php. Please refer to that.

$result = (new ArrayProcessor())->process($query, $rows);

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

object(Lampager\PaginationResult)#1 (5) {
  ["records"]=>
  array(5) {
    [0]=>
    array(5) {
      ["id"]=>
      int(3)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "foo"
      ["created_at"]=>
      string(19) "2017-01-10 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-20 00:00:00"
    }
    [1]=>
    array(5) {
      ["id"]=>
      int(5)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "bar"
      ["created_at"]=>
      string(19) "2017-01-05 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-20 00:00:00"
    }
    [2]=>
    array(5) {
      ["id"]=>
      int(4)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "baz"
      ["created_at"]=>
      string(19) "2017-01-05 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-20 00:00:00"
    }
    [3]=>
    array(5) {
      ["id"]=>
      int(2)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "qux"
      ["created_at"]=>
      string(19) "2017-01-17 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-18 00:00:00"
    }
    [4]=>
    array(5) {
      ["id"]=>
      int(1)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "quux"
      ["created_at"]=>
      string(19) "2017-01-16 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-18 00:00:00"
    }
  }
  ["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)
  }
}

Question: How about Tuple Comparison?

With this feature, SQL statements should be simpler. However, according to SQL Feature Comparison, some RDBMS, such as SQLServer, do not support this syntax. Therefore, Lampager continuously uses redundant statements.

It is also useful for Doctrine 2 since its DQL lexer does not support the syntax and triggers parse errors.

Classes

NameTypeParent Class
Implemented Interface
Description
Lampager\PaginatorClass Fluent factory for building Query
Lampager\AbstractProcessorAbstract Class Receive fetched records and format them
Lampager\PaginationResultClass Processor wraps result with this by default
Lampager\ArrayProcessorClassLampager\AbstractProcessorSimple Processor implementation for pure PDO
Lampager\ArrayCursorClassLampager\Contracts\CursorSimple Cursor implementation for pure PDO
Arrays are automatically wrapped with this
Lampager\QueryClass SQL configuration container generated by Paginator
Lampager\Query\...Class Child components of Query
Lampager\Contracts\CursorInterface Indicates parameters for retrieving previous/next records
Lampager\Contracts\FormatterInterface Formatter interface pluggable to Processor
Lampager\Concerns\HasProcessorTrait Helper for extended Paginator providing convenient accessibility to Processor

API

Paginator::orderBy()
Paginator::orderByDesc()
Paginator::clearOrderBy()

Add or clear cursor parameter name for ORDER BY statement.
At least one parameter required.

Paginator::orderBy(string $column, string $direction = 'asc'): $this
Paginator::orderByDesc(string $column): $this
Paginator::clearOrderBy(): $this

IMPORTANT: The last key MUST be the primary key.

e.g. $paginator->orderBy('updated_at')->orderBy('id')

Arguments

  • (string) $column
    Table column name.
  • (string) $direction
    "asc" or "desc".

Paginator::limit()

Define the pagination limit.

Paginator::limit(int $limit): $this

Arguments

  • (int) $limit
    Positive integer.

Paginator::forward()
Paginator::backward()

Define the pagination direction.

Paginator::forward(bool $forward = true): $this
Paginator::backward(bool $backward = true): $this

Forward (Default)

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor
    ===============>
[8] [ 7, 6, 5, 4, 3] [2]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor

Backward

    <===============
[2] [ 3, 4, 5, 6, 7] [8]
 |                |   └ next cursor
 |                └ current cursor
 └ previous cursor
    <===============
[8] [ 7, 6, 5, 4, 3] [2]
 |                |   └ next cursor
 |                └ current cursor
 └ previous cursor

IMPORTANT: You need previous cursor to retrieve more results.

Paginator::inclusive()
Paginator::exclusive()

Paginator::inclusive(bool $inclusive = true): $this
Paginator::exclusive(bool $exclusive = true): $this

Change the behavior of handling cursor.

Inclusive (Default)

Current cursor will be included in the current page.

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor
    <===============
[2] [ 3, 4, 5, 6, 7] [8]
 |                |   └ next cursor
 |                └ current cursor
 └ previous cursor

Exclusive

Current cursor will not be included in the current page.

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |                └ next cursor
 └ current cursor
    <===============
[2] [ 3, 4, 5, 6, 7] [8]
      |               |
      |               └ current cursor
      └ previous cursor

Paginator::unseekable()
Paginator::seekable()

Paginator::unseekable(bool $unseekable = true): $this
Paginator::seekable(bool $seekable = true): $this

Define that the pagination result should contain both of the next cursor and the previous cursor.

  • unseekable() always requires one simple SELECT query. (Default)
  • seekable() may require SELECT ... UNION ALL SELECT ... query when the cursor parameters are not empty.

Unseekable (Default)

    ===============>
[?] [ 3, 4, 5, 6, 7] [8]
      |               └ next cursor
      └ current cursor

Seekable

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor

Always when the current cursor parameters are empty

===============>
[ 1, 2, 3, 4, 5] [6]
                  └ next cursor

Paginator::fromArray()

Define options from an associative array.

Paginator::fromArray(array $options): $this

Arguments

  • (array) $options
    Associative array that contains the following keys.
    • (int) limit
    • (bool) backward / forward
    • (bool) exclusive / inclusive
    • (bool) seekable / unseekable
    • (string[][]) $orders

e.g.

[
    'limit' => 30,
    'backward' => true,
    'unseekable' => false,
    'orders' => [
        ['created_at', 'asc'],
        ['id', 'asc'],
    ],
]

Paginator::configure()

Generate Query corresponding to the current cursor.

Paginator::configure(Cursor|array $cursor = []): Query

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 the initial page, omit this parameter or pass an empty array.
    • For subsequent pages, pass all parameters. Partial parameters are not allowed.

AbstractProcessor::process()

Receive a pair of Query and fetched rows to analyze and format them.

AbstractProcessor::process(Query $query, mixed $rows): mixed

Arguments

  • (Query) $query
  • (mixed) $rows
    Fetched records from database. Typically it should be an array or a Traversable.

Return Value

(mixed)

By default, an instance of \Lampager\PaginationResult is returned. All fields are public.

e.g.

object(Lampager\PaginationResult)#1 (5) {
  ["records"]=>
  array(5) {
    /* ... */
  }
  ["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)
  }
}

Note that

  • hasPrevious/hasNext will be false when there are no more results for the corresponding direction.
  • Either hasPrevious/hasNext will be null when $cursor is empty or seekable() is not be enabled.

PaginationResult::getIterator()

It can be directly traversed using foreach thanks to the interface \IteratorAggregate.

AbstractProcessor::getIterator(): \ArrayIterator

Return Value

(mixed)

ArrayIterator instance that wraps records.

AbstractProcessor::useFormatter()
AbstractProcessor::restoreFormatter()

Override or restore the formatter for the pagination result.

AbstractProcessor::useFormatter(Formatter|callable $formatter): $this
AbstractProcessor::restoreFormatter(): $this

Callable Formatter Example

<?php

use Lampager\Query;
use Lampager\ArrayProcessor;
use Lampager\PaginationResult;

$formatter = function ($rows, array $meta, Query $query) {
    // Drop table prefix in meta properties (e.g. "posts.updated_at" -> "updated_at")
    foreach (array_filter($meta, 'is_array') as $property => $cursor) {
        foreach ($cursor as $column => $field) {
            unset($meta[$property][$column]);
            $segments = explode('.', $column);
            $meta[$property][end($segments)] = $field;
        }
    }
    return new PaginationResult($rows, $meta);
};

$result = (new ArrayProcessor())->useFormatter($formatter)->process($query, $rows);

Class Formatter Example

<?php

use Lampager\Query;
use Lampager\ArrayProcessor;
use Lampager\PaginationResult;
use Lampager\Contracts\Formatter;

class DropTablePrefix implements Formatter
{
    public function format($rows, array $meta, Query $query)
    {
        // Drop table prefix in meta properties (e.g. "posts.updated_at" -> "updated_at")
        foreach (array_filter($meta, 'is_array') as $property => $cursor) {
            foreach ($cursor as $column => $field) {
                unset($meta[$property][$column]);
                $segments = explode('.', $column);
                $meta[$property][end($segments)] = $field;
            }
        }
        return new PaginationResult($rows, $meta);
    }
}

$result = (new ArrayProcessor())->useFormatter(DropTablePrefix::class)->process($query, $rows);

AbstractProcessor::setDefaultFormatter()
AbstractProcessor::restoreDefaultFormatter()

Globally override or restore the formatter.

static AbstractProcessor::setDefaultFormatter(Formatter|callable $formatter): void
static AbstractProcessor::restoreDefaultFormatter(): void

Example (Laravel)

<?php

use Illuminate\Database\Eloquent\Builder;
use Lampager\Query;
use Lampager\Laravel\Processor as IlluminateProcessor;

IlluminateProcessor::setDefaultFormatter(function ($rows, array $meta, Query $query) {

   // Note:
   //    $builder is provided from extended Paginator.
   //    For example, lampager/lampager-laravel provides QueryBuilder, EloquentBuilder or Relation.
   $builder = $query->builder();

   switch ($builder instanceof Builder ? $builder->getModel() : null) {

       case Post::class:
           return (new PostFormatter())->format($rows, $meta, $query);

       case Comment::class:
           return (new CommentFormatter())->format($rows, $meta, $query);

       default:
           return new PaginationResult($rows, $meta);
   }
});

$posts = Post::lampager()->orderBy('created_at')->orderBy('id')->paginate();
$comments = Comment::lampager()->orderBy('created_at')->orderBy('id')->paginate();

Author: lampager
Source Code: https://github.com/lampager/lampager 
License: MIT license

#php #pagination 

What is GEEK

Buddha Community

Lampager: Rapid Pagination for Various PHP Frameworks

Hire PHP Developer - Best PHP Web Frameworks for Web Development

A framework that can drastically cut down the requirement to write original code to develop the web apps as per your requirement is PHP Framework. PHP frameworks offer code libraries for commonly used functions to reduce the development time.

Want to use PHP Web Frameworks for your web applications?

WebClues Infotech offers a service to hire dedicated PHP developers for all of the below-mentioned frameworks

  • Laravel Developer
  • Codeigniter Developer
  • Yii Developer
  • Zend Developer
  • Cake PHP Developer
  • Core PHP Developer

Not sure which framework to use for your PHP web application?

Contact us

Schedule Interview with PHP Developer https://bit.ly/3dsTWf0

Email: sales@webcluesinfotech.com

#hire php developer #hire php web developers #hire php developer in 2021 #hire php developers & dedicated php programmers #hire php developers india #hire and outsource freelance php developers

Lampager: Rapid Pagination for Various PHP Frameworks

Lampager Core

The core package of Lampager

Requirements

  • PHP: ^5.6 || ^7.0 || ^8.0

Installing

composer require lampager/lampager

Usage

Basically you don't need to directly use this package. For example, if you use Laravel, install lampager/lampager-laravel.

However, you can manually use like this:

use Lampager\Paginator;
use Lampager\ArrayProcessor;

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

$query = (new Paginator())
    ->forward()
    ->limit(5)
    ->orderByDesc('updated_at') // ORDER BY `updated_at` DESC, `created_at` DESC, `id` DESC
    ->orderByDesc('created_at')
    ->orderByDesc('id')
    ->seekable()
    ->configure($cursor);

$rows = run_your_query_using_PDO($query); // Note: SQLite3 driver example is bundled in the tests/StubPaginator.php. Please refer to that.

$result = (new ArrayProcessor())->process($query, $rows);

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

object(Lampager\PaginationResult)#1 (5) {
  ["records"]=>
  array(5) {
    [0]=>
    array(5) {
      ["id"]=>
      int(3)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "foo"
      ["created_at"]=>
      string(19) "2017-01-10 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-20 00:00:00"
    }
    [1]=>
    array(5) {
      ["id"]=>
      int(5)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "bar"
      ["created_at"]=>
      string(19) "2017-01-05 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-20 00:00:00"
    }
    [2]=>
    array(5) {
      ["id"]=>
      int(4)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "baz"
      ["created_at"]=>
      string(19) "2017-01-05 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-20 00:00:00"
    }
    [3]=>
    array(5) {
      ["id"]=>
      int(2)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "qux"
      ["created_at"]=>
      string(19) "2017-01-17 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-18 00:00:00"
    }
    [4]=>
    array(5) {
      ["id"]=>
      int(1)
      ["user_id"]=>
      int(1)
      ["text"]=>
      string(3) "quux"
      ["created_at"]=>
      string(19) "2017-01-16 00:00:00"
      ["updated_at"]=>
      string(19) "2017-01-18 00:00:00"
    }
  }
  ["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)
  }
}

Question: How about Tuple Comparison?

With this feature, SQL statements should be simpler. However, according to SQL Feature Comparison, some RDBMS, such as SQLServer, do not support this syntax. Therefore, Lampager continuously uses redundant statements.

It is also useful for Doctrine 2 since its DQL lexer does not support the syntax and triggers parse errors.

Classes

NameTypeParent Class
Implemented Interface
Description
Lampager\PaginatorClass Fluent factory for building Query
Lampager\AbstractProcessorAbstract Class Receive fetched records and format them
Lampager\PaginationResultClass Processor wraps result with this by default
Lampager\ArrayProcessorClassLampager\AbstractProcessorSimple Processor implementation for pure PDO
Lampager\ArrayCursorClassLampager\Contracts\CursorSimple Cursor implementation for pure PDO
Arrays are automatically wrapped with this
Lampager\QueryClass SQL configuration container generated by Paginator
Lampager\Query\...Class Child components of Query
Lampager\Contracts\CursorInterface Indicates parameters for retrieving previous/next records
Lampager\Contracts\FormatterInterface Formatter interface pluggable to Processor
Lampager\Concerns\HasProcessorTrait Helper for extended Paginator providing convenient accessibility to Processor

API

Paginator::orderBy()
Paginator::orderByDesc()
Paginator::clearOrderBy()

Add or clear cursor parameter name for ORDER BY statement.
At least one parameter required.

Paginator::orderBy(string $column, string $direction = 'asc'): $this
Paginator::orderByDesc(string $column): $this
Paginator::clearOrderBy(): $this

IMPORTANT: The last key MUST be the primary key.

e.g. $paginator->orderBy('updated_at')->orderBy('id')

Arguments

  • (string) $column
    Table column name.
  • (string) $direction
    "asc" or "desc".

Paginator::limit()

Define the pagination limit.

Paginator::limit(int $limit): $this

Arguments

  • (int) $limit
    Positive integer.

Paginator::forward()
Paginator::backward()

Define the pagination direction.

Paginator::forward(bool $forward = true): $this
Paginator::backward(bool $backward = true): $this

Forward (Default)

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor
    ===============>
[8] [ 7, 6, 5, 4, 3] [2]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor

Backward

    <===============
[2] [ 3, 4, 5, 6, 7] [8]
 |                |   └ next cursor
 |                └ current cursor
 └ previous cursor
    <===============
[8] [ 7, 6, 5, 4, 3] [2]
 |                |   └ next cursor
 |                └ current cursor
 └ previous cursor

IMPORTANT: You need previous cursor to retrieve more results.

Paginator::inclusive()
Paginator::exclusive()

Paginator::inclusive(bool $inclusive = true): $this
Paginator::exclusive(bool $exclusive = true): $this

Change the behavior of handling cursor.

Inclusive (Default)

Current cursor will be included in the current page.

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor
    <===============
[2] [ 3, 4, 5, 6, 7] [8]
 |                |   └ next cursor
 |                └ current cursor
 └ previous cursor

Exclusive

Current cursor will not be included in the current page.

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |                └ next cursor
 └ current cursor
    <===============
[2] [ 3, 4, 5, 6, 7] [8]
      |               |
      |               └ current cursor
      └ previous cursor

Paginator::unseekable()
Paginator::seekable()

Paginator::unseekable(bool $unseekable = true): $this
Paginator::seekable(bool $seekable = true): $this

Define that the pagination result should contain both of the next cursor and the previous cursor.

  • unseekable() always requires one simple SELECT query. (Default)
  • seekable() may require SELECT ... UNION ALL SELECT ... query when the cursor parameters are not empty.

Unseekable (Default)

    ===============>
[?] [ 3, 4, 5, 6, 7] [8]
      |               └ next cursor
      └ current cursor

Seekable

    ===============>
[2] [ 3, 4, 5, 6, 7] [8]
 |    |               └ next cursor
 |    └ current cursor
 └ previous cursor

Always when the current cursor parameters are empty

===============>
[ 1, 2, 3, 4, 5] [6]
                  └ next cursor

Paginator::fromArray()

Define options from an associative array.

Paginator::fromArray(array $options): $this

Arguments

  • (array) $options
    Associative array that contains the following keys.
    • (int) limit
    • (bool) backward / forward
    • (bool) exclusive / inclusive
    • (bool) seekable / unseekable
    • (string[][]) $orders

e.g.

[
    'limit' => 30,
    'backward' => true,
    'unseekable' => false,
    'orders' => [
        ['created_at', 'asc'],
        ['id', 'asc'],
    ],
]

Paginator::configure()

Generate Query corresponding to the current cursor.

Paginator::configure(Cursor|array $cursor = []): Query

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 the initial page, omit this parameter or pass an empty array.
    • For subsequent pages, pass all parameters. Partial parameters are not allowed.

AbstractProcessor::process()

Receive a pair of Query and fetched rows to analyze and format them.

AbstractProcessor::process(Query $query, mixed $rows): mixed

Arguments

  • (Query) $query
  • (mixed) $rows
    Fetched records from database. Typically it should be an array or a Traversable.

Return Value

(mixed)

By default, an instance of \Lampager\PaginationResult is returned. All fields are public.

e.g.

object(Lampager\PaginationResult)#1 (5) {
  ["records"]=>
  array(5) {
    /* ... */
  }
  ["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)
  }
}

Note that

  • hasPrevious/hasNext will be false when there are no more results for the corresponding direction.
  • Either hasPrevious/hasNext will be null when $cursor is empty or seekable() is not be enabled.

PaginationResult::getIterator()

It can be directly traversed using foreach thanks to the interface \IteratorAggregate.

AbstractProcessor::getIterator(): \ArrayIterator

Return Value

(mixed)

ArrayIterator instance that wraps records.

AbstractProcessor::useFormatter()
AbstractProcessor::restoreFormatter()

Override or restore the formatter for the pagination result.

AbstractProcessor::useFormatter(Formatter|callable $formatter): $this
AbstractProcessor::restoreFormatter(): $this

Callable Formatter Example

<?php

use Lampager\Query;
use Lampager\ArrayProcessor;
use Lampager\PaginationResult;

$formatter = function ($rows, array $meta, Query $query) {
    // Drop table prefix in meta properties (e.g. "posts.updated_at" -> "updated_at")
    foreach (array_filter($meta, 'is_array') as $property => $cursor) {
        foreach ($cursor as $column => $field) {
            unset($meta[$property][$column]);
            $segments = explode('.', $column);
            $meta[$property][end($segments)] = $field;
        }
    }
    return new PaginationResult($rows, $meta);
};

$result = (new ArrayProcessor())->useFormatter($formatter)->process($query, $rows);

Class Formatter Example

<?php

use Lampager\Query;
use Lampager\ArrayProcessor;
use Lampager\PaginationResult;
use Lampager\Contracts\Formatter;

class DropTablePrefix implements Formatter
{
    public function format($rows, array $meta, Query $query)
    {
        // Drop table prefix in meta properties (e.g. "posts.updated_at" -> "updated_at")
        foreach (array_filter($meta, 'is_array') as $property => $cursor) {
            foreach ($cursor as $column => $field) {
                unset($meta[$property][$column]);
                $segments = explode('.', $column);
                $meta[$property][end($segments)] = $field;
            }
        }
        return new PaginationResult($rows, $meta);
    }
}

$result = (new ArrayProcessor())->useFormatter(DropTablePrefix::class)->process($query, $rows);

AbstractProcessor::setDefaultFormatter()
AbstractProcessor::restoreDefaultFormatter()

Globally override or restore the formatter.

static AbstractProcessor::setDefaultFormatter(Formatter|callable $formatter): void
static AbstractProcessor::restoreDefaultFormatter(): void

Example (Laravel)

<?php

use Illuminate\Database\Eloquent\Builder;
use Lampager\Query;
use Lampager\Laravel\Processor as IlluminateProcessor;

IlluminateProcessor::setDefaultFormatter(function ($rows, array $meta, Query $query) {

   // Note:
   //    $builder is provided from extended Paginator.
   //    For example, lampager/lampager-laravel provides QueryBuilder, EloquentBuilder or Relation.
   $builder = $query->builder();

   switch ($builder instanceof Builder ? $builder->getModel() : null) {

       case Post::class:
           return (new PostFormatter())->format($rows, $meta, $query);

       case Comment::class:
           return (new CommentFormatter())->format($rows, $meta, $query);

       default:
           return new PaginationResult($rows, $meta);
   }
});

$posts = Post::lampager()->orderBy('created_at')->orderBy('id')->paginate();
$comments = Comment::lampager()->orderBy('created_at')->orderBy('id')->paginate();

Author: lampager
Source Code: https://github.com/lampager/lampager 
License: MIT license

#php #pagination 

Mike  Kozey

Mike Kozey

1617423780

10 of the Best PHP Testing Frameworks for 2021

We will discuss how the best PHP testing frameworks approach test automation and what pros or cons they all offer. Let’s look at the best PHP frameworks.

A framework is a collection or set of tools and processes that work together to support testing and developmental activities. It contains various utility libraries, reusable modules, test data setup, and other dependencies. Be it web development or testing, there are multiple frameworks that can enhance your team’s efficiency and productivity. Web testing, in particular, has a plethora of frameworks, and selecting a framework that suits your needs depends on your language of choice.

Amongst all server-side programming languages,  80% of websites use PHP, and the right framework can make the job easier. We decided to dive deeper into PHP and find out what the best PHP testing frameworks are. In this blog, we will be focusing on automated testing frameworks and will be listing out the best PHP frameworks that will allow you to write your test cases in a standard format.

Best PHP Testing Frameworks of 2021

Several frameworks have been and are being used for development and testing purposes. But each one is unique in its own way and offers unique features. We will discuss how the best PHP testing frameworks approach test automation and what pros or cons they all offer. Without further ado, let’s look at the best PHP frameworks.

  1. PHPUnit
  2. Codeception
  3. Storyplayer
  4. SeleniumHQ
  5. Behat
  6. Atoum
  7. SimpleTest
  8. phpSpec
  9. Peridot
  10. Kahlan

#php #php framework #php frameworks

Hire PHP Developer

Looking to develop a PHP based website from scratch or revamp your existing website?

HourlyDeveloper.io has always been an industry leader for companies and business owners looking to hire PHP web developer. By choosing to Hire PHP Developer from our company, you can always expect the best results. Our PHP services and solutions are always flexible which means that no matter the nature of your project, you can always count on us for getting the best PHP expertise.

Consult with our experts: https://bit.ly/3aEGxPy

#hire php developer #php developer #php development company #php development services #php development #php

Lawson  Wehner

Lawson Wehner

1617703800

The Best PHP Frameworks To Use for Web Development in 2021

Wondering which PHP framework is best for web development in 2021? Then you are in right place. Here we will discuss various PHP frameworks in detail.

Well, PHP (Hypertext Preprocessor) is one of those programming languages which are developed with built-in web development capabilities. Besides, The programmers can embed the code written in this popular server-side programming language seamlessly into HTML code through the Script tag.

Now, before we start the list of PHP frameworks, let’s discuss it in short.

What is PHP Framework?

A PHP framework is a platform to create PHP web applications. PHP frameworks provide code libraries for commonly used functions, cutting down on the amount of original code you need to write. Furthermore, PHP Framework provides a basic structure for streamlining the development of web apps. In addition, Developers use them because they speed up the development process. Above all, the responsiveness of websites and applications built using PHP frameworks helps businesses fulfill their performance needs.

Now, there are a number of frameworks available in PHP technology like  Laravel,  Codeigniter,  Symfony,  CakePHP, which we have mentioned in this list, that you can use for web development.

If you are working on a PHP project, then you can check the collection of   Laravel admin templates (free download).

Laravel

Symfony

Codeigniter

Cakephp

YII2

Zend

Phalcon

Fuel PHP

Slim

Lumen

#php-framework #web-dev #php #php