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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

ページネーション

Webアプリケーションにおいて、1ページに収まらないコンテンツを、各ページへのリンクを並べてアクセスしやすくする手法をページネーションと呼びます。

Q&A

解決済

1回答

1263閲覧

PHPで条件付のページネーションがうまくいかない

spcl

総合スコア19

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

ページネーション

Webアプリケーションにおいて、1ページに収まらないコンテンツを、各ページへのリンクを並べてアクセスしやすくする手法をページネーションと呼びます。

0グッド

0クリップ

投稿2018/08/25 03:08

質問失礼します。

ただいま練習でローカル環境でPHPとMysqlの勉強をしています。

以前はデータベースに登録している全てのレコードをページネーションを付けて表示する方法が分からず
こちらで質問させていただき無事解決できました。
下記がその質問です。
https://teratail.com/questions/140851

今回はここから派生?して
ある列の値が指定した値だけのデータをページネーションをつけて表示したいのですがうまくいきません。

下記はソースコードになります。

カテゴリーを選択

<form id="selectcate" name="selectcate" method="post" action="menu-category.php"> <dl> <dt> <label for="kind">種類</label> </dt> <dd> <select name="kind"> <option value="魚">魚</option> <option value="肉">肉</option> <option value="野菜">野菜</option> <option value="ドリンク">ドリンク</option> </select> </dd> </dl> <input type="submit" value="検索"> </form>

初めに作った表示画面

<?php require('dbconnect.php'); if (isset($_REQUEST['page'])) { $page = $_REQUEST['page']; } else { $page = 1; } $page = max($page, 1); $category = $_REQUEST['kind']; //最終ページを取得 $cnt = $mysqli->query('SELECT COUNT(kind = "$category") AS cnt FROM menu'); $table = mysqli_fetch_assoc($cnt); $maxPage = ceil($table['cnt'] / 5); $page = min($page, $maxPage); $start = ($page - 1) * 5; ?> <div id="menu_list"> <table class="menu_list"> <tr> <th>商品管理ID</ht> <th>カテゴリー</ht> <th class="menu_name">商品名</ht> <th>価格</ht> <th class="menu_remarks">備考</ht> </tr> <?php echo($category); $recodeSet = $mysqli->query("SELECT * FROM menu WHERE kind = '".$category."' ORDER BY id LIMIT $start, 5"); while($table = mysqli_fetch_assoc($recodeSet)){ ?> <tr> <td class="menu_content"><?php echo(htmlspecialchars($table['id'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['kind'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['name'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['price'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['remarks'])); ?></td> </tr> <?php } ?> </table> <ul class="paging"> <?php if($page > 1){ ?> <li><a href="menu-category.php?page=<?php print($page - 1); ?>" onclick="document.form1.submit();return false;">前のページ</a></li> <form name="form1" method="POST" action="menu-category.php?page=<?php print($page - 1); ?>"> <input type=hidden name="kind" value="<?php echo($category);?>"> <?php } else { ?> <?php } ?> <?php if($page < $maxPage){ ?> <li><a href="menu-category.php?page=<?php print($page + 1); ?>" onclick="document.form2.submit();return false;">次のページ</a></li> <form name="form2" method="POST" action="menu-category.php?page=<?php print($page + 1); ?>"> <input type=hidden name="kind" value="<?php echo($category);?>"> <?php } else { ?> <?php } ?> </ul> </div>

これだと最大ページが5まであることになり本来は魚を選んだ場合はカウントの結果が7つなので2ページ目が最終ページなります。
しかしsqlでカウントしてかつ、特定の列の値の指定が足りないと気付き(思い)
sql文にWHERE = kind "$category"を足した。

ちなみにですがMySqlで
SELECT COUNT(kind = '魚') AS cnt FROM menu WHERE kind = '魚';
の文で希望通りの結果(7)が表示されました。

それを踏まえ新しく作ったコードが次のコードです。

修正版

<?php require('dbconnect.php'); if (isset($_REQUEST['page'])) { $page = $_REQUEST['page']; } else { $page = 1; } $page = max($page, 1); $category = $_REQUEST['kind']; //最終ページを取得 $cntsql = 'SELECT COUNT(kind = '."$category".') AS cnt FROM menu WHERE kind = '."$category".' '; var_dump($cntsql); // ここで値を確認していますが望み通りのSQLができているはずです。 $cnt = $mysqli->query($cntsql); $table = mysqli_fetch_assoc($cnt); $maxPage = ceil($table['cnt'] / 5); $page = min($page, $maxPage); $start = ($page - 1) * 5; ?> <div id="menu_list"> <table class="menu_list"> <tr> <th>商品管理ID</ht> <th>カテゴリー</ht> <th class="menu_name">商品名</ht> <th>価格</ht> <th class="menu_remarks">備考</ht> </tr> <?php echo "$category</br>"; $statement = 'SELECT * FROM menu WHERE kind = '."$category".' ORDER BY id LIMIT '.$start.', 5'; var_dump($statement); // ここで$startが0のはずが-5になります。ということは最終ページの取得がうまくいっていない。。 $recodeSet = $mysqli->query($statement); while($table = mysqli_fetch_assoc($recodeSet)){ ?> <tr> <td class="menu_content"><?php echo(htmlspecialchars($table['id'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['kind'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['name'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['price'])); ?></td> <td class="menu_content"><?php echo(htmlspecialchars($table['remarks'])); ?></td> </tr> <?php } ?> </table> <ul class="paging"> <?php if($page > 1){ ?> <li><a href="menu-category.php?page=<?php print($page - 1); ?>" onclick="document.form1.submit();return false;">前のページ</a></li> <form name="form1" method="POST" action="menu-category.php?page=<?php print($page - 1); ?>"> <input type=hidden name="kind" value="<?php echo($category);?>"> <?php } else { ?> <?php } ?> <?php if($page < $maxPage){ ?> <li><a href="menu-category.php?page=<?php print($page + 1); ?>" onclick="document.form2.submit();return false;">次のページ</a></li> <form name="form2" method="POST" action="menu-category.php?page=<?php print($page + 1); ?>"> <input type=hidden name="kind" value="<?php echo($category);?>"> <?php } else { ?> <?php } ?> </ul> </div>

$startが-5のせいで何も表示されなくなりました。
表示されるエラーは2つあり2とも
Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given in

該当のコードの場所は
$table = mysqli_fetch_assoc($cnt);
while($table = mysqli_fetch_assoc($recodeSet)){
になります。

解決方法が見出せないのでご教授いただける方がいましたらどうかよろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/08/25 04:11

count内で式とかなかなか聞かないのでひとまず列名だけにしてみてください。
spcl

2018/08/25 04:26

SELECT COUNT(kind) AS cnt FROM menu WHERE kind = '魚';でも同じ結果がでました!エラーは変わりません。
m.ts10806

2018/08/25 04:36

ロジックとは関係ない部分ですが、変数名が保管している情報に則したものになっていませんね。それだけで読みづらいコードになっています。あまり意味を成してないダブルクォーテーションも気になりますし…。SQLインジェクションの対策もされていませんね。さておき、実行されているSQLをvar_dumpされていますが、その出力結果のSQLを直接mysqlで実行すると想定通りの値がとれますか?もし、とれない場合SQLがおかしい可能席もありますがDBに何かないとも言えません。エラーログを確認すると共に、再現確認したいのでDBの定義とサンプルデータをcreate tableとinsert文でご提示ください
m.ts10806

2018/08/25 04:56

回答してます。「事前に用意したSQLにはなっていない」のが原因です。クォーテーションは特別な意味を持つのでそれを文字列として認識させるには少し工夫が必要になります。まあ、初学者あるあるですけど
guest

回答1

0

ベストアンサー

とりあえずkind($category)が文字列ぽいのでそのままだとSQLとして正しくありません。

SQLとしては
WHERE kind = '魚'
のようにならないといけません。

今の記述を活かすなら

php

1WHERE kind = ¥''.$category.'¥'

こうですが、このままだとSQLインジェクションの脆弱性があるので
エスケープ関数をかませるか、そもそもpdoに切り替えるかしてください。

投稿2018/08/25 04:44

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

spcl

2018/08/25 06:02

やはり クォーテーションがおかしかったので文字列として認識してもらえてなかったんですね。 しかし\マークをつけることは知りませんでした。 \の使い方も調べます。 またセキュリティーについても教えていただきありがとうございます。 すこしPDOについて検索してみてみましたけど難しそうだ。。。。 理解できるか不安ですががんばって勉強します!
spcl

2018/08/25 06:02

この度もご回答いただきありがとうございます!!
m.ts10806

2018/08/25 06:16

¥については「エスケープシーケンス」です。phpに限らずJavaScriptでもJavaでも多くの言語に出てくる考え方なので覚えておいてください。 pdoについてはセキュリティ面も考慮すると有用です。Qiitaなどにもわかりやすいサンプルは沢山転がっているので参考にして見てください
m.ts10806

2018/08/25 06:17

今回だとダブルクォーテーションを括りに使っていればSQLのシングルクォーテーションのところにエスケープシーケンスは不要です。 状況に応じて使い分け、使いやすい方を場面場面で採用してください
spcl

2018/08/25 06:26

エスケープシーケンスについある程度理解できた気がします! 予約言語もエスケープできるとか!? おっしゃる通りでダブルクォーテーションでしたら\は不要でした! いろいろとPHPを使って作ってみたいものがありますがまずはPDOを勉強ですね! 諦めずがんばってみます! 本当にご丁寧にありがとうございます!
m.ts10806

2018/08/25 08:45

「予約語は使わない」が原則ですけどね どうしても使いたい場合はクォーテーションでくくると「文字列」として認識されるので使えるのは使えます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問