LoginSignup
10
11

More than 5 years have passed since last update.

PHPでページネーション

Last updated at Posted at 2018-01-16

毎回アプリケーションを作るたびに実装しているので面倒になったのでメモ

BaseTrait.php
<?php

namespace App\Model;

trait BaseTrait
{

    private static $instance;

    private function __construct()
    {
        // new from private only
    }

    public static function getInstance()
    {
        if ( ! self::$instance)
        {
            self::$instance = new static();
        }

        return self::$instance;
    }
}
Page.php
<?php

namespace App\Model;

class Page
{

    use BaseTrait;

    private $page_unit;
    private $default_page;
    private $page_link;

    private function __construct()
    {
        $this->setPageUnit(3);// 1ページに表示する件数
        $this->setDefaultPage(1);// 最初のページ
        $this->setPageLink(5);// ページネーションのリンクを表示する件数(中央をアクティブにしたいので奇数)
    }

    public function setPageUnit(int $number)
    {
        $this->page_unit = $number < 1 ? 1 : $number;
    }

    public function setDefaultPage(int $number)
    {
        $this->default_page = $number < 1 ? 1 : $number;
    }

    public function setPageLink(int $number)
    {
        $this->page_link = $number < 1 ? 1 : $number;
    }

    /**
     * ページネーションの表示に必要な情報の取得
     * これで取得したoffsetとlimitで表示するアイテムのリストは別途取得すること
     *
     * @param int $page ページ位置(クエリーストリングから渡ってくる想定)
     * @param int $item_count 全アイテム数
     * @return array
     */
    public function getPageData(int $page = null, int $item_count): array
    {
        $item_count = $item_count < 1 ? 1 : $item_count;

        $data = [];
        $data['limit'] = $this->page_unit;
        $data['max_page'] = (int)(($item_count - 1) / $this->page_unit) + 1;

        if (is_null($page) || $page === 0 || $data['max_page'] < $page)
        {
            $data['current_page'] = $this->default_page;
            $data['offset'] = 0;
        }
        else
        {
            $data['current_page'] = $page;
            $data['offset'] = ($page - 1) * $this->page_unit;
        }

        $data['page_link'] = $this->page_link;
        if ($data['current_page'] < $data['max_page'] - (int)($data['page_link'] / 2))
        {
            $start_number = $data['current_page'] - (int)($data['page_link'] / 2);
        }
        else
        {
            $start_number = $data['max_page'] - $data['page_link'] + 1;
        }
        $data['start_page'] = $start_number < $this->default_page ? $this->default_page : $start_number;

        $data['pre_page'] = $data['start_page'] > 1 ? $data['start_page'] - 1 : null;
        $end_number = $data['start_page'] + $data['page_link'] - 1;
        $data['next_page'] = $end_number < $data['max_page'] ? $end_number + 1 : null;

        return $data;
    }
}

コントローラ

use App\Model\Page;
~~~~~~~~~~~~~~~~~~

$page = 処理;// クエリーストリングから取得(int|null)
$item_count = 処理;// DB等から対象データ件数取得(int)

$page_model = Page::getInstance();
$data['page_data'] = $page_model->getPageData($page, $item_count);

// DB等から$data['page_data']['offset']と$data['page_data']['limit']で表示データ取得
$data['item_object_list'] = 処理;

// $dataをテンプレートエンジンに渡す

Bootstrap付きテンプレートエンジンで表示

  • blade
<div class="text-center">
    <ul class="pagination">
        @for ($i = $page_data['start_page']; $i < $page_data['start_page'] + $page_data['page_link']; $i++)
            @if ($i > $page_data['max_page'])
                @break
            @endif
            @if ($i === $page_data['current_page'])
                <li class="active"><a href="?page={{ $i }}">{{ $i }}</a></li>
            @else
                <li><a href="?page={{ $i }}">{{ $i }}</a></li>
            @endif
        @endfor
    </ul>
</div>

<!--ここにアイテム-->
<table class="table table-striped table-hover table-bordered">
    <tr>
        <th>ID</th>
        <th>Name</th>
    </tr>
    @foreach ($item_object_list as $item_object)
        <tr>
            <td>{{ $item_object->id }}</td>
            <td>{{ $item_object->name }}</td>
        </tr>
    @endforeach
</table>
  • Smarty
<div class="text-center">
    <ul class="pagination">
        {for $i = $page_data['start_page'] to ($page_data['start_page'] + $page_data['page_link'] - 1)}
            {if $i > $page_data['max_page']}
                {break}
            {/if}
            {if $i === $page_data['current_page']}
                <li class="active"><a href="?page={$i}">{$i}</a></li>
            {else}
                <li><a href="?page={$i}">{$i}</a></li>
            {/if}
        {/for}
    </ul>
</div>

<!--ここにアイテム-->
<table class="table table-striped table-hover table-bordered">
    <tr>
        <th>ID</th>
        <th>Name</th>
    </tr>
    {foreach from=$item_object_list item=item_object}
        <tr>
            <td>{$item_object->id}</td>
            <td>{$item_object->name}</td>
        </tr>
    {/foreach}
</table>

pagenation.png

前へ次へのリンクを作る際は$data['pre_page']$data['next_page']を使う。

10
11
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
10
11