PHP7とlaravel5.6でページネーションを実装してみた

## 実際に実装する機能
- データ（名前、テキスト）入力、保存
- データ表示
- ページネーション

ちなみに、laravelは[Homestead](https://readouble.com/laravel/5.6/ja/homestead.html)を利用しています。

## フレームワークを使わないでそのままPHP7で実装

内部の処理画面

```setting.php
function showData()
{
    // GETで現在のページ数を取得
    if (isset($_GET['page'])) {
        $page = (int)$_GET['page'];
    } else {
        $page = 1;
    }

    $dbh = new PDO(
     'mysql:dbname=db_name;host=localhost;charset=utf8mb4',
     'dbuser',
     'dbuser',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ]
);

    try {

        // データ抽出処理

        // 10件ずつデータを取得するSQLにて、取り出すときのスタートの位置を計算
        if ($page > 1) {
            $start = ($page * 10) - 10;
        } else {
            $start = 0;
        }

        // DBから過去のデータを1ページに10件ずつ取得
        $sel_sql = "SELECT name,text FROM table_name ORDER BY id desc LIMIT ?, 10 ";
        $sel_prepare = $dbh->prepare($sel_sql);
        $sel_prepare->bindValue(1, $start, PDO::PARAM_INT);
        $sel_prepare->execute();

        // 変数に取得内容の配列を格納
        // front.php内でも使用するため$sel_resultはグローバル宣言
        global $sel_result;
        $sel_result = $sel_prepare->fetchAll(PDO::FETCH_ASSOC);


        // pagination処理

        // 全ページ数を取得するため、DBにあるデータ数を取得
        $page_sql = "SELECT COUNT(*) id FROM table_name";
        $page_num = $dbh->prepare($page_sql);
        $page_num->execute();
        $page_num = $page_num->fetchColumn();

        // 全ページ数を取得
        // 全ページ数：データが１２件だったら2ページ、３１件だったら４ページ
        // front.php内でも使用するため$paginationはグローバル宣言
        global $pagination;
        $pagination = ceil($page_num / 10);

        // DBの接続を切る
        $dbh = null;

    } catch (PDOException $e) {

        echo 'データの取得が失敗しました。<br>';
        echo $e->getMessage();
        exit;
    }
```



フロント画面

```front.php
<!DOCTYPE HTML>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>タイトル</title>
</head>
<body>
<p>入力してください</p>
<form action="front.php" method="post">
    <span>名前</span><br>
    <input type="text" name="name"><br>
    <span>テキスト</span><br>
    <textarea name="text" rows="10"></textarea><br>
    <input type="submit">
</form>
<br>
<table border="1">
    <thead>
    <th>name</th>
    <th>text</th>
    </thead>
    <tbody>
<?php

    require_once('setting.php');

    showData();

    foreach ($sel_result as $key => $val) {

        $name_before = $val['name'];
        $text_before = $val['text'];

        // 改行を反映させる
        $name_after = nl2br(str_replace('\n', "\n", $name_before));
        $text_after = nl2br(str_replace('\n', "\n", $text_before));


        echo '<tr><td>' . $name_after . ' </td>';
        echo '<td>' . $text_after . '</td></tr>';
    }

    echo '</tbody>';
    echo '</table><br>';
    
    // 10件ずつわけたページ先のリンクを表示
    for ($x = 1; $x <= $pagination; $x++) {
        echo '<a href="?page=' . $x . '">' . $x . '</a>';
    }


?>

<br>
<br>
</body>
</html>
```

[![Screenshot from Gyazo](https://gyazo.com/28f2dd3ec769b5d8a32ae2f997f2f7e7/raw)](https://gyazo.com/28f2dd3ec769b5d8a32ae2f997f2f7e7)



色々と大変。。


## laravel5.6上で実装すると

ルーティング画面

```web.php
<?php

Route::get('/', 'PostController@index');
Route::post('/front/post', 'PostController@post');
```


コントローラー画面

```PostController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;

class PostController extends Controller
{

    public function index()
    {

    $posts = Post::orderBy('created_at', 'desc')->paginate(10);

    return view('front', [
        'posts' => $posts
    ]);

    }

    public function post(Request $request)
    {

    $post = new Post();
    $post->name = $request->name;
    $post->text = $request->text;
    $post->save();

    return redirect('/');
    
    }

}
```

ビュー画面

```front.blade.php
@extends('layouts.app')

@section('content')

    <div class="body">
        <div class="top">
        <p>入力してください</p>
        <form action="/front/post" method="post">
            {{ csrf_field() }}
            <span>名前</span><br>
            <input type="text" name="name"><br>
            <span>テキスト</span><br>
            <textarea name="text" rows="10"></textarea><br>
            <input type="submit">
        </form>
        </div>
        <br>
        <br>
        <br>
    {{-- データが取得できれば以下表示 --}}
    @if(count($posts) > 0)
    <div class="posts-table">
        <table border="1">
            <thead>
            <th>name</th>
            <th>text</th>
            </thead>
            <tbody>
            @foreach($posts as $post)
                <tr>
                    {{-- 改行を反映させて表示 --}}
                    <td>{!! nl2br(str_replace('\n', "\n", e($post->name))) !!}</td>
                    <td>{!! nl2br(str_replace('\n', "\n", e($post->text))) !!}</td>
                </tr>
            @endforeach
            </tbody>
        </table>
        {{-- ページリンクを表示 --}}
        {{ $posts->links() }}
    </div>
    @endif
    </div>
@endsection
```



[![Screenshot from Gyazo](https://gyazo.com/edfe5e1eae53d9df040ef98e31047b30/raw)](https://gyazo.com/edfe5e1eae53d9df040ef98e31047b30)



コントローラー画面に``$post = Post::orderBy('created_at', 'desc')->paginate(10);``
ビュー画面に``{{ $posts->links() }}``
を付け加えるだけ。

ただしcssをviewのページで読み込んでいないと、ページネーション部分の見た目が以下のようになってしまう。
<img width="124" alt="スクリーンショット 2018-03-13 15.47.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/225607/9a7d49b7-bc98-9140-5c94-9c23a4388d48.png">

なのでビューの共通部分でデフォルトで入っているcssを読み込みます。

```app.blade.php

<!DOCTYPE html>
<html lang="ja">
<head>
    <title>タイトル</title>
    <link rel="stylesheet" href="{{ asset('/css/app.css') }}">
</head>

<body>
<div class="container">
    <nav class="navbar navbar-default">
    </nav>
</div>

@yield('content')
</body>
</html>
```

すると以下のようなページネーションが表示されます。
とっても簡単…！
<img width="316" alt="スクリーンショット 2018-03-13 15.52.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/225607/34cc9e03-91d7-0a6d-4c6c-308d91832e8e.png">




## 参考
https://readouble.com/laravel/5.6/ja/pagination.html
https://manablog.org/php-pagination/