LoginSignup
5
7

More than 5 years have passed since last update.

Ginq 専用の Phalcon Paginator を書いた

Posted at

去年書いた Phalcon Model::find の結果を Ginq にする方法 という記事で暇があったら書くって言ってたやつです。
最近は暇があったら二百うん年後のボストンに行ってます(Fallout4)。でもやっぱり必要になったので書きました。

Why

Model find 結果を Ginq に統一しているので、サーバサイドページングを Ginq に対応させたかった。
超ニッチ。

Code

名前空間は書いてません。適宜適切に記述してください。

GinqPaginator.php
<?php

use Phalcon\Paginator\Exception;
use Phalcon\Paginator\AdapterInterface;

class GinqPaginator implements AdapterInterface
{
    /** @type array */
    protected $config;

    /** @type int */
    protected $page;

    /** @type int */
    protected $limitRows;

    public function __construct($config)
    {
        $this->config = $config;
        if (isset($config['limit'])) {
            $this->limitRows = $config['limit'];
        }
        if (isset($config['page'])) {
            $this->page = $config['page'];
        }
    }

    public function setCurrentPage($page)
    {
        $this->page = $page;
        return $this;
    }

    public function getPaginate()
    {
        $limit = intval($this->limitRows);
        $config = $this->config;
        /** @var Ginq $items */
        $items = $config['data'];
        $pageNumber = intval($this->page);

        if (!(class_exists("Ginq\\Ginq") and $items instanceof \Ginq\Ginq)) {
            throw new Exception("Invalid data for paginator");
        }

        if ($pageNumber <= 0) {
            $pageNumber = 1;
        }

        if ($limit <= 0) {
            throw new Exception("The limit number is zero or less");
        }

        $n = $items->count();
        $offset = $limit * ($pageNumber - 1);
        $totalPages = (int)ceil($n / $limit);

        if ($offset > 0) $items = $items->drop($offset);
        $items = $items->take($limit);

        $next = $pageNumber < $totalPages
            ? $pageNumber + 1
            : $totalPages;

        $before = $pageNumber > 1
            ? $pageNumber - 1
            : 1;

        return (object)[
            'items' => $items->toList(),
            'first' => 1,
            'before' => $before,
            'current' => $pageNumber,
            'last' => $totalPages,
            'next' => $next,
            'total_pages' => $totalPages,
            'total_items' => $n,
            'limit' => $limit,
        ];
    }
}

How

EntryController.php
class EntryController extendes Controller {

    public function entriesAction()
    {
        $limit = 10;    // 1ページに表示する数
        // クエリストリングからページ番号を取得 ?page=1 
        $page_num = $this->request->get('page', ['int'], 1);
        $entries = Entries::find(); // なんかたくさん取得する(返ってくるのは Ginq)

        // Ginq, ページ内表示数, ページ番号を渡す
        $paginator = new GinqPaginator([
            'data' => $entries,
            'limit' => $limit,
            'page' => $page_num,
        ]);
        // 今回のページを取得
        $page = $paginator->getPaginate();
        $this->view->setVar('page', $page);
    }

}
entries.volt
{{ page.current }} <!-- 今のページ番号 -->
{{ page.before }} <!-- 前のページ番号 -->
{{ page.next }} <!-- 次のページ番号 -->
{{ page.total_pages }} <!-- 何ページあるか -->
{{ page.total_items }} <!-- 全部でいくつあるか -->
<ul>
  {% for entry in page.items %} <!-- ページ内のアイテムをイテレート -->
    <li>{{ entry.title }}</li>
  {% endfor %}
</ul>
5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7