tobento/service-pagination

轻松构建分页控件。

1.0.1 2021-10-31 07:26 UTC

This package is auto-updated.

Last update: 2024-09-29 05:29:54 UTC


README

分页服务提供了一种轻松构建分页控件的方法。

目录

入门

运行以下命令安装分页服务项目的最新版本。

composer require tobento/service-pagination

需求

  • PHP 8.0 或更高版本

亮点

  • 框架无关,可与任何项目一起使用
  • 解耦设计
  • 自定义渲染
  • 自定义URL生成

截图



简单示例

use Tobento\Service\Pagination\Pagination;

$pagination = new Pagination(
    totalItems: 200,
    currentPage: 3,
);

渲染分页

<?= $pagination->render() ?>

// or just
<?= $pagination ?>

文档

分页

创建分页

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\PaginationInterface;
use Tobento\Service\Pagination\UrlGenerator;
use Tobento\Service\Pagination\MenuRenderer;

$pagination = new Pagination(
    totalItems: 200,
    currentPage: 3,
    itemsPerPage: 50,
    maxPagesToShow: 10,
    maxItemsPerPage: 1000,
    urlGenerator: (new UrlGenerator())->addPageUrl('#{num}'),
    renderer: new MenuRenderer('prev', 'next'),
);

var_dump($pagination instanceof PaginationInterface);
// bool(true)

使用方法

您可以通过以下“使用方法”更改一些数据或实现,并返回一个新实例。

withCurrentPage

use Tobento\Service\Pagination\Pagination;

$pagination = new Pagination(totalItems: 200);

$newPagination = $pagination->withCurrentPage(6);

var_dump($pagination === $newPagination);
// bool(false)

withItemsPerPage

use Tobento\Service\Pagination\Pagination;

$pagination = new Pagination(totalItems: 200);

$newPagination = $pagination->withItemsPerPage(30);

var_dump($pagination === $newPagination);
// bool(false)

withMaxPagesToShow

use Tobento\Service\Pagination\Pagination;

$pagination = new Pagination(totalItems: 200);

$newPagination = $pagination->withMaxPagesToShow(6);

var_dump($pagination === $newPagination);
// bool(false)

withUrlGenerator

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\UrlGenerator;

$pagination = new Pagination(totalItems: 200);

$newPagination = $pagination->withUrlGenerator(new UrlGenerator());

var_dump($pagination === $newPagination);
// bool(false)

withRenderer

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\MenuRenderer;

$pagination = new Pagination(totalItems: 200);

$newPagination = $pagination->withRenderer(new MenuRenderer());

var_dump($pagination === $newPagination);
// bool(false)

分页数据

对于自定义渲染器,您可能需要以下数据,以验证页码或限制查询。

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\PageInterface;

$pagination = new Pagination(
    totalItems: 200,
    currentPage: 3,
    itemsPerPage: 50,
    maxPagesToShow: 10,
);

var_dump($pagination->getTotalItems());
// int(200)

var_dump($pagination->getTotalItemsFrom());
// int(101)

var_dump($pagination->getTotalItemsTo());
// int(150)

var_dump($pagination->getItemsPerPage());
// int(50)

var_dump($pagination->getItemsOffset());
// int(100)

var_dump($pagination->hasPages());
// bool(true)

$pages = $pagination->getPages();
// array<int, PageInterface>

$pages = $pagination->getTotalPages();
// int(4)

var_dump($pagination->hasPage(num: 5));
// bool(false)

var_dump($pagination->hasCurrentPage());
// bool(true)

var_dump($pagination->getCurrentPage());
// int(3)

var_dump($pagination->getPrevPageUrl());
// string(6) "page/2"

var_dump($pagination->getNextPageUrl());
// NULL

当前页验证

建议检查当前页是否存在,特别是如果您从用户输入或基于URL参数设置当前页。

use Tobento\Service\Pagination\Pagination;

$pagination = new Pagination(
    totalItems: 200,
    currentPage: 12,
    itemsPerPage: 50,
);

if (! $pagination->hasCurrentPage()) {
    // handle if current page does not exist.
    // redirect, page not found or whatever fits your application design.
    $pagination = $pagination->withCurrentPage(1);
}

渲染分页

根据您的需求,有多种渲染分页的方法。

菜单渲染器

菜单渲染器是默认的分页渲染器。它使用 菜单服务 生成分页HTML。

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\MenuRenderer;

$pagination = new Pagination(
    totalItems: 200,
    currentPage: 3,
    itemsPerPage: 30,
    renderer: new MenuRenderer(previousText: 'prev', nextText: 'next'),
);

echo $pagination;

输出

<ul class="pagination">
    <li><a href="page/2">prev</a></li>
    <li class="page"><a href="page/1">1</a></li>
    <li class="page"><a href="page/2">2</a></li>
    <li class="current"><span>3</span></li>
    <li class="page"><a href="page/4">4</a></li>
    <li class="page"><a href="page/5">5</a></li>
    <li class="page"><a href="page/6">6</a></li>
    <li class="page"><a href="page/7">7</a></li>
    <li><a href="page/4">next</a></li>
</ul>

自定义渲染器

您可以为您的应用程序编写自己的渲染器。以下示例使用 视图服务 生成分页HTML。

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\RendererInterface;
use Tobento\Service\Pagination\PaginationInterface;
use Tobento\Service\View\ViewInterface;
use Tobento\Service\View\View;
use Tobento\Service\View\PhpRenderer;
use Tobento\Service\Dir\Dirs;
use Tobento\Service\Dir\Dir;
use Tobento\Service\View\Data;
use Tobento\Service\View\Assets;

$view = new View(
    new PhpRenderer(
        new Dirs(
            new Dir('home/private/views/')
        )
    ),
    new Data(),
    new Assets('home/public/src/', 'https://www.example.com/src/')
);

class ViewRenderer implements RendererInterface
{
    public function __construct(
        private ViewInterface $view,
        private string $viewToRender = 'service/pagination',
    ) {}
    
    public function render(PaginationInterface $pagination): string
    {        
        return $this->view->render(
            $this->viewToRender,
            ['pagination' => $pagination]
        );
    }
}

$pagination = new Pagination(
    totalItems: 500,
    currentPage: 2,
    renderer: new ViewRenderer($view),
);

echo $pagination;

视图模板

<?php if ($pagination->getTotalPages() > 1) { ?>
    <nav class="pagination">
        <ul class="pagination">    
            <?php if ($pagination->getPrevPageUrl()) { ?>
                <li><a href="<?= $view->esc($pagination->getPrevPageUrl()) ?>">Previous</a></li>
            <?php } ?>

            <?php foreach($pagination->getPages() as $page) { ?>
                <?php if ($page->url() && ! $page->current()) { ?>
                    <li><a href="<?= $view->esc($page->url()) ?>"><?= $view->esc($page->name()) ?></a></li>
                <?php } else { ?>
                    <li><span class="<?= $page->current() ? 'current': '' ?>"><?= $view->esc($page->name()) ?></span></li>
                <?php } ?>
            <?php } ?>

            <?php if ($pagination->getNextPageUrl()) { ?>
                <li><a href="<?= $view->esc($pagination->getNextPageUrl()) ?>">Next</a></li>
            <?php } ?>           
        </ul>
    </nav>
<?php } ?>

<div class="pagination-info">
    <p>
        Showing <?= $view->esc($pagination->getTotalItemsFrom()) ?>
        - <?= $view->esc($pagination->getTotalItemsTo()) ?>
        from <?= $view->esc($pagination->getTotalItems()) ?> records.
    </p>
</div>

URL生成

默认URL生成器

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\UrlGenerator;

$urlGenerator = new UrlGenerator();

// url pattern for all pages:
$urlGenerator->addPageUrl(url: 'page/{num}', placeholder: '{num}');

// url pattern for page number 1 only:
$urlGenerator->addPageUrl(url: 'page', placeholder: null, page: 1);


$pagination = new Pagination(
    totalItems: 500,
    currentPage: 3,
    urlGenerator: $urlGenerator,
);

echo $pagination;

自定义URL生成器

您可以为您的应用程序设计编写自定义的URL生成器。

use Tobento\Service\Pagination\Pagination;
use Tobento\Service\Pagination\UrlGeneratorInterface;

class CustomUrlGenerator implements UrlGeneratorInterface
{
    /**
     * Generate the url for the specified page number.
     *
     * @param int $pageNumber
     * @return string The generated url.
     */
    public function generate(int $pageNumber): string
    {
        // generate the url for the specified page number.
        return '';
    }
}

$pagination = new Pagination(
    totalItems: 500,
    currentPage: 3,
    urlGenerator: new CustomUrlGenerator(),
);

echo $pagination;

致谢

一些想法和代码片段取自 Jasongrimes php-paginator