lampager/lampager-cakephp

CakePHP 5 的快速分页

安装数: 30,354

依赖: 0

建议者: 1

安全性: 0

星标: 5

关注者: 9

分支: 3

开放问题: 0

类型:cakephp-plugin

v3.0.0 2024-04-21 12:21 UTC

This package is auto-updated.

Last update: 2024-09-21 13:32:24 UTC


README

lampager-cakephp

CI Workflow Coverage Status Scrutinizer Code Quality

CakePHP 的 Lampager

无需使用 OFFSET 的快速分页

要求

注意

安装

composer require lampager/lampager-cakephp:^3.0

对于 SQLite 用户,请参阅 SQLite 进行配置。

基本用法

简单地将它作为 Composer 包安装,并在以下方法之一中使用它

  • 在控制器中使用(通过 \Lampager\Cake\Datasource\Paginator
  • 在表中使用(通过 \Lampager\Cake\Model\Behavior\LampagerBehavior

在控制器中使用

首先,在您的控制器类中配置 $paginate 以使用 \Lampager\Cake\Datasource\Paginator

namespace App\Controller;

use Cake\Controller\Controller;
use Lampager\Cake\Datasource\Paginator;

class AppController extends Controller
{
    public $paginate = [
        'className' => Paginator::class,
    ];
}

使用烹饪书中的描述: 分页。注意 Lampager 的特定选项,如 forwardseekablecursor

$query = $this->Posts
    ->where(['Posts.type' => 'public'])
    ->orderByDesc('created')
    ->orderByDesc('id')
    ->limit(10);

$posts = $this->paginate($query, [
    'forward' => true,
    'seekable' => true,
    'cursor' => [
        'id' => 4,
        'created' => '2020-01-01 10:00:00',
    ],
]);

$this->set('posts', $posts);

在表中使用

在您的表类(建议使用 AppTable)中初始化 LampagerBehavior 并简单使用 lampager()

namespace App\Model\Table;

use Cake\ORM\Table;
use Lampager\Cake\Model\Behavior\LampagerBehavior;

class AppTable extends Table
{
    public function initialize(array $config): void
    {
        parent::initialize($config);

        $this->addBehavior(LampagerBehavior::class);
    }
}

查询构建器(\Lampager\Cake\ORM\Query)扩展了普通的 \Cake\ORM\Query 并与 \Lampager\Paginator 混合。请注意,\Lampager\Paginator 中的某些方法,如 orderBy()orderByDesc()clearOrderBy(),没有公开,因为它们的签名与 CakePHP 查询构建器不兼容。

$cursor = [
    'id' => 4,
    'created' => '2020-01-01 10:00:00',
    'modified' => '2020-01-01 12:00:00',
];

/** @var \Lampager\Cake\PaginationResult $latest */
$latest = $this->lampager()
    ->forward()
    ->seekable()
    ->cursor($cursor)
    ->limit(10)
    ->orderByDesc('Posts.modified')
    ->orderByDesc('Posts.created')
    ->orderByDesc('Posts.id')
    ->paginate();

foreach ($latest as $post) {
    /** @var \Cake\ORM\Entity $post */
    debug($post->id);
    debug($post->created);
    debug($post->modified);
}

CakePHP 查询构建器的方法,例如 where(),是可用的。也接受 \Cake\Database\Expression\QueryExpression

/** @var \Lampager\Cake\PaginationResult $drafts */
$drafts = $this->lampager()
    ->where(['type' => 'draft'])
    ->forward()
    ->seekable()
    ->cursor($cursor)
    ->limit(10)
    ->orderByDesc($this->selectQuery()->newExpr('modified'))
    ->orderByDesc($this->selectQuery()->newExpr('created'))
    ->orderByDesc($this->selectQuery()->newExpr('id'))
    ->paginate();

/** @var \Cake\ORM\Entity $sample */
$sample = $drafts->sample();

/** @var int $count */
$count = $drafts->count();

另请参阅: lampager/lampager

API

另请参阅: lampager/lampager

LampagerBehavior::lampager()

以与 CakePHP 完全相同的方式从表中构建 Lampager 查询。

LampagerBehavior::lampager(): \Lampager\Cake\ORM\Query

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

创建一个新的分页器实例。这些方法不打算直接在您的代码中使用。

static Paginator::create(\Cake\ORM\Query\SelectQuery $builder): static
Paginator::__construct(\Cake\ORM\Query\SelectQuery $builder)

Paginator::transform()

将 Lampager 查询转换为 CakePHP 查询。

Paginator::transform(\Lampager\Query $query): \Cake\ORM\Query\SelectQuery

Paginator::build()

执行配置 + 转换。

Paginator::build(\Lampager\Contracts\Cursor|array $cursor = []): \Cake\ORM\Query\SelectQuery

Paginator::paginate()

执行配置 + 转换 + 处理。

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

参数

  • (mixed) $cursor
    包含 $column => $value 的关联数组或实现 \Lampager\Contracts\Cursor 的对象。它必须是 全部或无
    • 对于第一页,省略此参数或传递一个空数组。
    • 对于后续页面,传递所有参数。不允许部分参数。

返回值

例如,

(使用 \Cake\ORM\Query 的默认格式时)

object(Lampager\Cake\PaginationResult)#1 (6) {
  ["(help)"]=>
  string(44) "This is a Lampager Pagination Result object."
  ["records"]=>
  array(3) {
    [0]=>
    object(Cake\ORM\Entity)#2 (11) { ... }
    [1]=>
    object(Cake\ORM\Entity)#3 (11) { ... }
    [2]=>
    object(Cake\ORM\Entity)#4 (11) { ... }
  ["hasPrevious"]=>
  bool(false)
  ["previousCursor"]=>
  NULL
  ["hasNext"]=>
  bool(true)
  ["nextCursor"]=>
  array(2) {
    ["created"]=>
    object(Cake\I18n\Time)#5 (3) {
      ["date"]=>
      string(26) "2017-01-01 10:00:00.000000"
      ["timezone_type"]=>
      int(3)
      ["timezone"]=>
      string(3) "UTC"
    }
    ["id"]=>
    int(1)
  }
}

PaginationResult::__call()

\Lampager\Cake\PaginationResult 实现 \Cake\Datasource\Paging\PaginatedInterface

示例

本节描述了 lampager-cakephp 的实际用法。

在控制器中使用

下面的示例显示了如何从请求中接受一个游标参数并将其通过 PaginatorComponent::paginate() 传递。请确保您的 AppController 正确初始化了 Paginator,如上所述。

namespace App\Controller;

class PostsController extends AppController
{
    public $Posts = null;

    /**
     * This method shows how to pass options by a query and array.
     */
    public function query(): void
    {
        // Get cursor parameters
        $previous = json_decode($this->request->getQuery('previous_cursor'), true);
        $next = json_decode($this->request->getQuery('next_cursor'), true);
        $cursor = $previous ?: $next ?: [];

        // Query expression can be passed to PaginatorComponent::paginate() as normal
        $query = $this->Posts
            ->where(['Posts.type' => 'public'])
            ->orderByDesc('created')
            ->orderByDesc('id')
            ->limit(15);

        /** @var \Lampager\Cake\PaginationResult<\Cake\ORM\Entity> $posts */
        $posts = $this->paginate($query, [
            // If the previous_cursor is not set, paginate forward; otherwise backward
            'forward' => !$previous,
            'cursor' => $cursor,
            'seekable' => true,
        ]);

        $this->set('posts', $posts);
    }

    /**
     * This method shows how to pass options from an array.
     */
    public function options(): void
    {
        // Get cursor parameters
        $previous = json_decode($this->request->getQuery('previous_cursor'), true);
        $next = json_decode($this->request->getQuery('next_cursor'), true);
        $cursor = $previous ?: $next ?: [];

        /** @var \Lampager\Cake\PaginationResult<\Cake\ORM\Entity> $posts */
        $posts = $this->paginate('Posts', [
            // Lampager options
            // If the previous_cursor is not set, paginate forward; otherwise backward
            'forward' => !$previous,
            'cursor' => $cursor,
            'seekable' => true,

            // PaginatorComponent config
            'conditions' => [
                'type' => 'public',
            ],
            'order' => [
                'created' => 'DESC',
                'id' => 'DESC',
            ],
            'limit' => 15,
        ]);

        $this->set('posts', $posts);
    }
}

分页链接可以按以下方式输出

// If there is a next page, print pagination link
if ($posts->hasPrevious) {
    echo $this->Html->link('<< Previous', [
        'controller' => 'posts',
        'action' => 'index',
        '?' => [
            'previous_cursor' => json_encode($posts->previousCursor),
        ],
    ]);
}

// If there is a next page, print pagination link
if ($posts->hasNext) {
    echo $this->Html->link('Next >>', [
        'controller' => 'posts',
        'action' => 'index',
        '?' => [
            'next_cursor' => json_encode($posts->nextCursor),
        ],
    ]);
}

支持的数据库引擎

MySQL、MariaDB 和 PostgreSQL

支持!

Microsoft SQL Server

不支持。

SQLite

支持但需要额外的配置。

在SQLite中,UNION ALL语句不能结合带有ORDER BY子句的SELECT语句。为了使其工作,这些SELECT语句必须被一个子查询包裹,例如SELECT * FROM (...)。CakePHP没有原生处理这种情况,Lampager for CakePHP引入了\Lampager\Cake\Database\Driver\Sqlite,需要在您的应用程序中安装。在您的config/app.php中进行如下配置

return [
    'Datasources' => [
        'default' => [
            'className' => Connection::class,
            'driver' => \Lampager\Cake\Database\Driver\Sqlite::class,
            'username' => '********',
            'password' => '********',
            'database' => '********',
        ],
    ],
];