質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.03%

php sql ページング機能 取得内容が重複してしまう

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 338

h_r

score 10

現在、ECサイトの作成をしております。ユーザーごとに購入履歴を表示する履歴ページにてページング機能を実装したいのですがうまくいきません。
下記コードだと1ページあたり10件になりますが、各ページにて履歴内容が重複してしまいます。
(1ページ目(21-12件)、2ページ目(20-11件)のような表示になっている。
1ページ目(21-12件)、2ページ目(11-2件)にしたい)

関数部分

// 履歴テーブルから取得
function get_history($dbh, $user_id) {
    try {
        // SQL生成
        $sql = 'SELECT sake_master.sake_id, 
                    sake_master.name,
                    sake_master.price,
                    sake_master.img,
                    users_history.user_id,
                    users_history.amount,
                    users_history.buy_datetime
                    FROM sake_master
                    INNER JOIN users_history
                    ON sake_master.sake_id = users_history.sake_id
                    WHERE users_history.user_id = :user_id
                    ORDER BY buy_datetime DESC
                    LIMIT :start, :limit';
        // SQL文を実行する準備
        $stmt = $dbh->prepare($sql);
        $stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
        $stmt->bindParam(':start', getCurrentPage(), PDO::PARAM_INT);
        $stmt->bindValue(':limit', 10, PDO::PARAM_INT);
        // SQLを実行
        $stmt->execute();
        // レコードの取得
        $rows = $stmt->fetchAll();
} catch (PDOException $e) {
        throw $e;
    }
    return $rows;
}

// 履歴テーブルの件数を取得
function get_historyCount($dbh, $user_id) {
    try {
        // SQL生成
        $sql = 'SELECT COUNT(*)
                FROM users_history
                WHERE user_id = :user_id';
        // SQL文を実行する準備
        $stmt = $dbh->prepare($sql);
        $stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
        // SQLを実行
        $stmt->execute();
        // レコードの取得
        $count = $stmt->fetchColumn();
    } catch (PDOException $e) {
        throw $e;
    }
    return $count;
}

// 現在のページ番号を取得する
function getCurrentPage() {
    return (int) filter_input(INPUT_GET, 'page');
}

function pagination($count) {
    $limit = 10;

    //レコード総数がゼロのときは何も出力しない
    if (0 === $count) {
        return '';
    }

    //現在表示中のページ番号(ゼロスタート)
    $intCurrentPage = getCurrentPage();

    //ページの最大数
    $intMaxpage = ceil($count / $limit);

    //現在ページの前後3ページを出力
    $intStartpage = (2 < $intCurrentPage) ? $intCurrentPage - 3 : 0;
    var_dump($intCurrentPage);
    $intEndpage = (($intStartpage + 7) < $intMaxpage) ? $intStartpage + 7 : $intMaxpage;
    var_dump($count);

    //url組み立て
    $urlparams = filter_input_array(INPUT_GET);

    $items = array();

    //最初
    $urlparams['page'] = 0;
    $items[] = sprintf('<span><a href="?%s">%s</a></span>'
        , http_build_query($urlparams)
        , '最初'
    );

    //表示中のページが先頭ではない時
    if (0 < $intCurrentPage) {
        $urlparams['page'] = $intCurrentPage - 1;
        $items[] = sprintf('<span><a href="?%s">%s</a></span>'
            , http_build_query($urlparams)
            , '前へ'
        );
    }

    for ($i = $intStartpage; $i < $intEndpage; $i++) {
        $urlparams['page'] = $i;
        $items[] = sprintf('<span%s><a href="?%s">%s</a></span>'
            , ($intCurrentPage == $i) ? ' class="current"' : ''
            , http_build_query($urlparams)
            , $i + 1
        );
    }

    //表示中のページが最後ではない時
    if ($intCurrentPage < $intMaxpage) {
        $urlparams['page'] = $intCurrentPage + 1;
        $items[] = sprintf('<span><a href="?%s">%s</a></span>'
            , http_build_query($urlparams)
            , '次へ'
        );
    }

    //最後
    $urlparams['page'] = $intMaxpage - 1;
    $items[] = sprintf('<span><a href="?%s">%s</a></span>'
        , http_build_query($urlparams)
        , '最後'
    );

    return sprintf('<div class="pagination">%s</div>', implode(PHP_EOL, $items));
}

表示部分

<?php foreach($rows as $value) { ?>
            <?php if (count($rows) !== 0) { ?>
                <div class="layout">
                    <div class="i">
                        <img src="<?php print $img_dir . $value['img']; ?>" class="itemlist">
                    </div>
                    <div class="n">
                        <div class="nameprice">
                            <p class="list"><?php print $value['name']; ?></p>
                            <p class="list">価格¥<?php print $value['price']; ?></p>
                        </div>
                        <p class="list">数量<?php print $value['amount']; ?></p>
                        <p class="history">購入日<?php print $value['buy_datetime']; ?></p>
                    </div>
                </div>
            <?php } ?>
        <?php } ?>
        </div>
        <?php print pagination($count); ?>


https://qiita.com/ShibuyaKosuke/items/0c5c6df1fac218fbca38
こちらのサイトを参考にさせて頂きましたが、全体的にあまり理解できておりません。
ご教示頂ければ幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

ざっくり直すだけなら、
$stmt->bindParam(':start', getCurrentPage(), PDO::PARAM_INT);

$start = getCurrentPage() * 10;
$stmt->bindParam(':start', $start, PDO::PARAM_INT);


みたいな感じすればOKなはず。

理由はLIMIT句の文法(参考)と今のコードのstartがどうなっているかを確認して見比べればわかると思います。


参考にしているサンプルの方では
$start = getCurrentPage() * $limit;
という感じでもう少し使いやすくなっているので、もう一度サンプルをじっくり読んで理解を試みることをお勧めします。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/15 09:06

    ご回答ありがとうございます。取り急ぎ、ご指摘頂いた内容に変更したところ上手くいきましたのでベストアンサーにさせて頂きます。理由がなぜかは、またゆっくり時間のあるときに確認します。本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる