【PHP】ページネーション

`PHP`でページネーションを実装しました。
配列でデータを管理して、クリックされたボタンによって表示を条件分岐する処理になっています。

![pagenation02-min.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/349eadd6-81b1-69a9-487d-0e288220559a.gif)

#全体像
はじめに、実装する際の大まかな処理の流れについて説明していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/f438f900-ab18-64a0-164c-6e697352beea.png)
このように７つ投稿データをもっている配列、`$posts`があるとします。
こちらを３投稿ずつに分けてページネーション機能で表示したいときに、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/4c7dc572-7775-0f96-ac1d-9bf454e7c3b2.png)
上記のように配列`$block`に、３投稿ずつ入れます。
配列`$block`の引数を変数にして、クリックされたボタンによって変数に値を渡します。

では、実際に実装していきます。

##ブロックごとにデータを配分する
先ほど説明した、配列`$block`をつくります。
まずは、ページネーションでデータを表示させる一覧画面から確認していきます。

```post_list.php
<?php
$block=pagination_block($posts);

global $i;
if(empty($_POST['block'])){
  $_SESSION[$i]=0;
}
if(isset($_POST['block'])){
switch($_POST['block']){
  case '«':
    $_SESSION[$i]--;
  break;
  case '»':
    $_SESSION[$i]++;
  break;
  default:
  $_SESSION[$i] = $_POST['block']-1;
  break;
}
}

if(isset($block[0])):
  foreach($block[$_SESSION[$i]] as $post):
?>
<div class="post">
　<p><?= $post['text'] ?></p>
  <img src="/post/image/<?= $post['image'] ?>">
</div>
<?php endforeach ?>
<?php endif?>
```
`foreach`関数で`$block`のデータを順に表示しています。
`$_POST['block']`で`$_SESSION[$i]`の値を更新しているのですが、こちらは後ほど説明します。
`$posts`には、下記のような投稿データが７つ入っています。

```:$posts
Array
(
    [0] => Array
        (
            [id] => 7
            [text] => 投稿01
            [image] => 
            [user_id] => 38
            [created_at] => 2021-04-17 10:20:46
：
：
    [6] => Array
        (
            [id] => 1
            [text] => 投稿07
            [image] => 
            [user_id] => 38
            [created_at] => 2021-04-17 10:20:22
        )
)
```
それでは、最初に定義されている`pagination_block`関数から見ていきます。

```php:
function pagination_block($data){
  global $block;
  $data_count=count($data);
  $block_count=ceil($data_count/3);
  $k=0;
  for($i=0;$i<$block_count;$i++){
    for($j=0;$j<3;$j++){
        if($data_count==$k){
            break;
        }
        $block[$i][$j]=$data[$k];
        $k++;
    }
  }
  return $block;
}
```
`$data_count`で投稿数を取得し、`$block_count`では`$block`の要素数を取得しています。
`for文`でデータを１つずつ`$block`に渡していき、値を渡す回数`$k`が`$data_count`と同じ値になったときに`break`するような処理になっています。
ちなみに`$j`はページネーション機能で表示するデータ数を決めており、今回は３投稿ずつ表示するようにしています。

これで、`$block`に３投稿ずつデータを渡すことができました。
それではページネーションを実現するためのボタンを作成していきます。

##ページネーションのボタン作成
```pagination.php
<?php 
if(isset($block[1])):
    $block_count=count($block);
?>

    <form method="post" action="#">
    <nav aria-label="Page navigation">
      <ul class="pagination justify-content-center pagination-lg">
        <li class="page-item">
            <?php if($_SESSION[$i]==0):?>
                <input class="page-link first" name="block" type="submit" value="&laquo;" disabled>
            <?php else:?>
                <input class="page-link" name="block" type="submit" value="&laquo;">
            <?php endif;?>
        </li>
    
        <?php for($l=1;$l<$block_count+1;$l++){
        print'<li class="page-item"><input class="page-link" name="block" type="submit" value="'.$l.'"></li>';
        }?>
        <li class="page-item">
        <li class="page-item">
            <?php if($_SESSION[$i]==$block_count-1):?>
                <input class="page-link last" name="block" type="submit" value="&raquo;" disabled>
            <?php else:?>
                <input class="page-link" name="block" type="submit" value="&raquo;">
            <?php endif;?>
        </li>
        </li>
      </ul>
    </nav>
    </form>
    <?php endif; ?>
```
レイアウトは`Bootstrap4`を使用しています。

```pagination.php
if(isset($block[1])):
：
<?php endif; ?>
```
`$block[0]`しかデータがない場合は、ボタンを表示しないようにしており、

```pagination.php
：
<?php for($l=1;$l<$block_count+1;$l++){
 print'<li class="page-item"><input class="page-link" name="block" type="submit" value="'.$l.'"></li>';
}?>
：
```
こちらで`$block`の要素数だけボタンを表示するようにし、`value="'.$l.'"`でボタンに表示する値を指定しています。

```pagination.php
：
<?php if($_SESSION[$i]==0):?>
 <input class="page-link first" name="block" type="submit" value="&laquo;" disabled>
<?php else:?>
：
<?php if($_SESSION[$i]==$block_count-1):?>
 <input class="page-link last" name="block" type="submit" value="&raquo;" disabled>
<?php else:?>
：
```
`$block`の引数が`0`のときは、`<<（次ページ）`ボタンを無効にし、引数が`$blockの要素数より１少ない`場合は`>>（前ページ）`ボタンを無効にしています。

これらのボタンがクリックされたときに、`$_SESSION[$i]`の値が変わるような処理を`$_POST['block']`で実装します。

先ほどの`post_list.php`のページに戻りまして、

```post_list.php
if(isset($_POST['block'])){
 switch($_POST['block']){
   case '«':
     $_SESSION[$i]--;
   break;
   case '»':
     $_SESSION[$i]++;
   break;
   default:
     $_SESSION[$i] = $_POST['block']-1;
  break;
 }
}
```
クリックされたボタンによって、下記表のように`$_SESSION[$i]`の値が更新されるようになっています。

`$_POST['block']`|`$_SESSION[$i]`
---|---
<<(次ページ)|インクリメント
>>(前ページ)|デクリメント
ページ指定ボタン|ボタンの値 - 1

これでクリックされたボタンによって`$_POST['block']`の引数が更新されるようになり、表示されるデータが変更されるようになりました。