Chromeのページネーションと同じ動作するページネーションが実装できたっぽい

####ページネーションを作ったきっかけ

PHPでページネーションを自作せよ！という課題が出ました。

簡単なページネーションのやり方はネットに大量に上がってるし、何か自分で考えた機能を一つ持たせてみたいと思い、参考にできるアイデアを探しがてらChromeのページネーションをポチポチしていると
「Goooooooooogle」という風に「o」がページの数だけ連続して、表示されているページの部分だけ赤くなるのが面白かったので、Chromeのページネーションを実装できるかチャレンジしてみたところ、とりあえずは実装できたっぽいので、記録として記事にしておこうと思いました。

##実装

まずページネーションで表示するページ数と1ページあたりのリソース数を定数で持ちます。

```php
// ページネーションで表示するページ数
const RANGE = 10;

// 1ページに表示するリソース数
const ITEM_COUNT = 5;
```

クエリパラメーターからページ数を取得し、ページング対象リソースの件数をSQLを発行し取得します。（SQLの記述は省略しています）

```php
// クエリパラメーターからページ数を取得
$page = $_GET['page']; 

// "SQLの結果" -> 例) 77 (ページネーション対象リソースの件数) 
$total = "SQLの結果";
```
表示できる最大ページ数を `件数 / 1ページに表示するリソース数` で求めます。

```php
// 例) 77 / 5 を切り上げ -> 16
$maxPage = (int)ceil($total / ITEM_COUNT);
```

ページ数はクエリパラメーターから取得するため、URLを操作されて存在しないページ数が送信されてくる可能性があります。
そのため表示できる `最大ページ数よりも大きい値、もしくは1より小さい値` を取得した場合は1ページ目を表示します。

```php
if ($page > $maxPage || $page < 1) {
    $page = 1;
}
```

***

ここからはHTMLの**for文で使用する値**の準備をします。

**for文の初期値(startPage)は、ページネーションの最終ページ(endPage)からRANGE - 1を引いた値とします。**

Chromeでは7ページ目からページネーションに表示されている数字が変わります。表示が 2 ~ 11ページになりました。
![6AB08C4F-7666-4065-856B-AB3AC2C84091_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732098/2a952df0-52a1-75fe-351d-ec80fc618e78.jpeg)
7ページ目からということは、「`RANGE(10) / 2 + 1`」**6**ページより大きい場合は最終ページに「`page(7) + floor((RANGE - 1) / 2)(4)`」**11ページ**を設定します。

```php
//  最終ページ = 7 > 6 ? 11 : 10
$endPage = $page > RANGE / 2 + 1 ? (int)($page + floor((RANGE - 1) / 2)) : RANGE;
```
最終ページの値は、表示できる最大ページ数よりも大きくなってしまう場合があるので、表示できる**最大ページ数は超えないように調整**します。

```php
$endPage = min($endPage, $maxPage);
```

ページネーションに表示する最初のページ数を求めます。
こちらも**最初のページが1より小さくならないよう調整**します。

```php
$startPage = max($endPage - (RANGE - 1), 1);
```

ここまででページネーションを表示するために必要な値の準備は整いました。

###サンプルHTML

```php
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        .bold {
            font-weight: bold;
        }
    </style>
</head>
<body>
<div class="pagination bold">
    <p>
        <span>
            <?php if ($page > 1) { ?>
                <a href="/paginate?page=<?= $page - 1 ?>">< </a>
            <?php } ?>
        </span>
        <span style="color: #4285f4;">G</span>
        <?php for ($i = $startPage; $i <= $endPage; $i++) { ?>
            <span style="color: <?= $i == $page ? "#ea4335" : "#fbbc05" ?>;">a</span>
            <?php if ($i + 1 > $maxPage) {
                break;
            } ?>
        <?php } ?>
        <span style="color: #4285f4;">g</span>
        <span style="color: #34a853;">l</span>
        <span style="color: #ea4335;">e</span>
        <span>
            <?php if ($page < $maxPage) { ?>
                <a href="/paginate?page=<?= $page + 1 ?>"> ></a>
            <?php } ?>
        </span>
    </p>
    <?php for ($i = $startPage; $i <= $endPage; $i++) { ?>
        <a href="/paginate?page=<?= $i ?>">
            <sapn style="color: <?= $i == $page ? "#ea4335" : '' ?>;"><?= $i ?></span>
        </a>
        <?php if ($i + 1 > $maxPage) {
            break;
        } ?>
    <?php } ?>
</div>
</body>
```
こんな感じになりました。
繰り返す文字や、定義した定数の値を変更して遊んでみてください！
![4AAE7FAB-CCAA-4658-A533-90A555E5DAC5_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732098/c5b0be2a-58c3-9699-b15c-da179fcf85cf.jpeg)