beberlei/porpaginas

一个库,用于以通用的方式解决DAO/repository抽象的多个分页问题。

v2.1 2023-02-17 15:26 UTC

This package is auto-updated.

Last update: 2024-08-28 17:32:10 UTC


README

Build Status

这个库解决了与Repository类API相关的大量问题

  • 您需要不同方法来处理可分页和非分页的查找方法。
  • 您需要暴露底层数据源并从您的存储库返回查询对象。
  • 分页器的序列化应该可以轻松地为REST API实现。

Pagerfanta和KnpLabs Pager都没有解决这个问题,它们的API在这方面非常有问题。您需要从您的存储库返回查询对象或分页器的适配器才能使其正常工作,然后使用控制器侧的API将它们转换为分页结果集。

Porpaginas通过引入分页结果的合理抽象来解决此问题。为了渲染目的,您可以选择与Pagerfanta或KnpLabs Pager集成,这个库不涉及分页视图部分的重新实现。

该库的核心是Result接口

<?php
namespace Porpaginas;

interface Result extends Countable, IteratorAggregate
{
    /**
     * @param int $offset
     * @param int $limit
     * @return Page
     */
    public function take($offset, $limit);

    /**
     * Return the number of all results in the paginatable.
     *
     * @return int
     */
    public function count();

    /**
     * Return an iterator over all results of the paginatable.
     *
     * @return Iterator
     */
    public function getIterator();
}

此API为您提供了两种遍历可分页结果的方式,要么是完整的结果,要么是使用take()的页面的分页窗口。一个缺点是查询始终在Result内部懒加载执行,而不是直接在存储库中。

Result#take()返回的Page接口看起来像这样

<?php

namespace Porpaginas;

interface Page extends Countable, IteratorAggregate
{
    /**
     * Return the number of results on the current page.

     * @return int
     */
    public function count();

    /**
     * Return the number of ALL results in the paginatable.

     * @return int
     */
    public function totalCount();

    /**
     * Return an iterator over selected windows of results of the paginatable.
     *
     * @return Iterator
     */
    public function getIterator();
}

如果底层数据源本身是迭代器,您可以使用IteratorPage在自己的实现中。

支持的后端

  • 数组
  • Doctrine ORM

示例

以下是一个使用Doctrine ORM的示例

<?php
class UserRepository extends EntityRepository
{
    /**
     * @return \Porpaginas\Result
     */
    public function findAllUsers()
    {
        $qb = $this->createQueryBuilder('u')->orderBy('u.username');

        return new ORMQueryResult($qb);
    }
}

class UserController
{
    /**
     * @var UserRepository
     */
    private $userRepository;

    public function listAction(Request $request)
    {
        $result = $this->userRepository->findAllUsers();
        // no filtering by page, iterate full result

        return array('users' => $result);
    }

    public function porpaginasListAction(Request $request)
    {
        $result = $this->userRepository->findAllUsers();

        $paginator = $result->take(($request->get('page')-1) * 20, 20);

        return array('users' => $paginator);
    }
}

现在在porpaginasListAction的模板中使用porpaginas Twig扩展,例如

We found a total of <strong>{{ porpaginas_total(users) }}</strong> users:

<ul>
{% for user in users %}
    <li>{{ user.name }}</li>
{% endfor %}
</ul>

{{ porpaginas_render(users) }}

分页库支持

  • 对于Pagerfanta,请使用Porpaginas\Pagerfanta\PorpaginasAdapter并将结果作为第一个参数传递。

嵌入式分页器

您可以使用Porpaginas\Pager类来帮助您获取要显示的上一页和下一页的切片

$pager = Porpaginas\Pager::fromPage($page);

传递到模板

<nav class="pages">
    <ul>
        {% for page in pager.pages() %}
            <li class="{{ pager.isCurrent(page) ? 'active' }}">
                <a href="{{ page }}">{{ page }}</a>
            </li>
        {% endfor %}
    </ul>
</nav>