pagerfanta 不能直接在 codeigniter 中开箱即用,因其依赖 symfony 的 request 和 urlgenerator,而 ci 3/4 使用自有 uri 和输入处理机制,导致页码识别失败、链接错乱;ci 3 需手动传页码并实现 url 生成器,ci 4 推荐直接使用原生 pager 类。

Pagerfanta 不能直接在 CodeIgniter 中开箱即用,它不兼容 CI 的加载机制和请求上下文(比如 URL 路由、查询参数解析),强行集成会导致分页链接错乱、当前页码丢失、无法响应 GET 参数变化等问题。
为什么 Pagerfanta 和 CodeIgniter 原生流程冲突
Pagerfanta 默认依赖 Symfony 的 Request 对象提取 page 参数,并用 UrlGeneratorInterface 构建链接——而 CodeIgniter 3/4 都没有这些组件。CI 3 用 $this->uri->segment() 或 $this->input->get('page');CI 4 则通过 $this->request->getGet('page') 获取,且分页链接需适配路由风格(如 /news/page/2 或 /news?page=2)。
- 直接 new Pagerfanta($adapter) 后调用
getCurrentPage()会返回 1,永远不识别实际页码 -
getPaginationData()或getUrls()生成的链接是 Symfony 风格,不是 CI 的 base_url() + uri_string() 拼接逻辑 - 没有自动处理 CI 的 XSS 过滤、CSRF(如果开启)、或 URI 重写规则(如 .htaccess 隐藏 index.php)
CI 3 中手动桥接 Pagerfanta 的最小可行方案
必须绕过 Pagerfanta 的自动请求感知,显式传入当前页码和自定义 URL 生成器:
- 用
$this->input->get('page')获取页码,强制转为 int 并限制范围:max(1, (int)$this->input->get('page', true)) - 实现一个匿名函数作为
UrlGenerator:返回形如base_url('news/index/').$page(路径分页)或base_url('news').'?page='.$page(查询参数分页) - Adapter 推荐用
Pagerfanta\Adapter\Doctrine\ORMAdapter(配合 CI 的 Doctrine 库)或自定义ArrayAdapter/DoctrineDbalAdapter(需手动查总数+偏移数据) - 关键代码片段:
$page = max(1, (int)$this->input->get('page', true)); $adapter = new \Pagerfanta\Adapter\DoctrineDbalAdapter($queryBuilder, $totalCount); $paginator = new \Pagerfanta\Pagerfanta($adapter); $paginator->setCurrentPage($page); $paginator->setMaxPerPage(10); // 手动构造 URL $urlGenerator = function ($page) { return base_url('news/index/') . $page; }; $paginator->setUrlGenerator($urlGenerator);
CI 4 更推荐放弃 Pagerfanta,改用原生 Paginator + 自定义渲染
CI 4.3+ 内置 CodeIgniter\Pager\Pager 已足够灵活,且与 Model::paginate() 深度协同。Pagerfanta 在这里纯属冗余,还引入额外依赖和兼容风险。
- Model 中直接调用:
$posts = $this->postModel->where('status', 'published')->paginate(15, 'group1'); - View 中用
$pager->links('group1', 'bootstrap5')渲染,支持自定义模板(app/Views/pager/custom.php) - 若需完全控制 HTML,可取原始数据:
$pager->getDetails('group1')返回包含currentPage、total、perPage等字段的数组 - 注意:CI 4 的
paginate()默认从 URL 查询参数读page,但若用路径分页(如/posts/2),需在路由中声明'posts/(:num)' => 'Posts::index/$1',并在控制器里手动传参:$this->postModel->paginate(15, 'group1', $page)
真正卡住的点从来不是“能不能塞进 Pagerfanta”,而是你是否清楚当前项目用的是路径分页还是查询参数分页、是否启用了 URL 重写、以及 Model 层是否已封装好 count + limit/offset 逻辑——这些细节比选哪个分页库重要得多。











