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

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

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

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

Q&A

解決済

4回答

464閲覧

PHPでのページング機能とCSRF

gsuisk

総合スコア72

PHP

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

0グッド

0クリップ

投稿2017/09/19 18:00

編集2017/09/20 07:14

追記です。

わかりづらい質問をしてしまい、すみませんでした。GETのところを勘違いしていました。自己解決した部分もあるので改めました。

PHPでページング機能を実装したいです。

ユーザーが検索(POST)すると一致するレコード(投稿)を取り出して順に表示させたいです。

検索(POST)するときに、CSRF対策のトークンのチェックをしております。

ページングを実装できたのですが、2ページ目以降をクリックすると、トークンチェックで引っかかり、不正なPOST扱いになってしまいます。

ページングはGETリクエストで行っています。

トークンの設定は検索ページでhiddenで送り、検索一覧表示ページ(ページング実装したページ)の最初にトークンのチェックをしています。

なぜページングのGETリクエストがトークンチェックで引っかかってしまうのでしょうか?

教えていただけたら幸いです。

以前の質問を以下に復活させました。

PHPでページング機能を実装したいです。しかし$_GETをページ以外にも使っています。
実装したいのは、掲示板のようなものです。
(1) ユーザーが検索(POST)すると一致するレコード(投稿)を取り出して順に表示。
(2) 表示したレコードはURLになっており、詳細ページにリンクする。ここでGETリクエストを使用。
詳細ページ(detail.php)へのリンクは投稿idでGETリクエストしています。詳細ページでは再びDBにアクセスしてGETで送られたidをもとにレコードを取り出す仕組みです。

$result = $stm->fetchAll(PDO::FETCH_ASSOC); foreach ($result as $row) { echo '<a href="detail.php ?id=',$row['id'],'">', "詳細", "</a>"; echo "<br>"; }

1ページあたり5つのレコードを表示させたいです。
以下のように実装したのですが、GETリクエストが重なるからなのか2ページ目にリンクできません。汚いコードで申し訳ないですが、コードは以下です。

$pdo = new PDO($dsn, $user, $password); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); if (isset($_GET['page'])) { $page = (int)$_GET['page']; } else { $page = 1; } if ($page > 1) { $start = ($page * 5) - 5; } else { $start = 0; } //SQL文は省略します。 $sql = "ここに検索一致条件等を書いています。"; $sql.="LIMIT {$start}, 5"; $stm = $pdo->prepare($sql); $stm->execute($data); $result=$stm->fetchAll(PDO::FETCH_ASSOC); foreach ($result as $row) { echo '<a href="detail.php ?id=',$row['id'],'">', "詳細", "</a>"; echo "<br>"; } $page_num = $pdo->prepare(" SELECT COUNT(*) id FROM table "); $page_num->execute(); $page_num = $page_num->fetchColumn(); $pagination = ceil($page_num / 5); ?> <?php for ($i=1; $i<= $pagination ; $i++):?> <a href="?page=<?php echo $i ?>"><?php echo $i; ?></a> <?php endfor; ?>

この状態だと全ページ数が、全レコードをもとに計算されたページ数になってしまいます。(検索して一致したレコード数をもとにページ数がけいさんされていない。)
詳細ページへのGETである?idとページネーションへのGETである?pageを両立するにはどうすればよいでしょうか?
また、詳細ページへのGETである?idとページネーションへのGETである?pageを両立するにはどうすればよいでしょうか?
教えていただけたら幸いです。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2017/09/19 23:04

もう少し簡潔にまとめてください
kei344

2017/09/20 06:22

回答が付いた質問の編集は慎重に行ってください。タイプミス程度なら修正する事もありますが、本文を削除するのはやめましょう。
m.ts10806

2017/09/20 06:29 編集

編集時に元の文章を間違って消してしまったのでしょうか?「追記です」から始まっている良く分からない内容になってしまっています。質問と回答が噛み合わなくなってしまっています。元の質問を復帰させて追記部分を別質問とするか、削除した理由を明示してください。
m.ts10806

2017/09/20 06:31 編集

「自己解決した」とのことなので、元の質問文を復帰させた上で、自己解決できた内容を自身で回答しベストアンサーとして、追記した部分は別質問とするのがのぞましいように思います。ご検討ください。
gsuisk

2017/09/20 06:35

ごめんなさい。今気が付きました、、、質問の分かりづらいところを修正した後、追記がすぐにわかるように上に追記文章を載せたつもりでした。質問全部が削除されてしまっていてしまい本当に申し訳ありません...
gsuisk

2017/09/20 06:36

Kei344さん、すみませんでした。別質問にすべきでした。Kei344さんのご回答はとても参考になるものでした。本当にすみませんでした。
m.ts10806

2017/09/20 06:42

まあ、焦らずやりましょう。
gsuisk

2017/09/20 06:49

ごめんなさい、、ご回答して下さった皆様をベストアンサーにしたいところですが、私の不注意で質問が複雑になってしまったので、このような形とさせていただきます。
m.ts10806

2017/09/20 07:05

元の質問文を復帰させた上で解決とすべきです。元の文章は履歴から確認できます。
m.ts10806

2017/09/20 07:06 編集

履歴はタイトル下の編集{日時}がリンクになっているのでそこから編集履歴のページに遷移します。
guest

回答4

0

http_build_query 使えばよいのでは。

URL

1https://example.com?foo=bar&baz=boom&cow=milk&php=hypertext+processor

【PHP: http_build_query - Manual】
http://php.net/manual/ja/function.http-build-query.php

【http_build_queryを使うときの注意点(PHP) – Sometime PHP】
http://www.multiburst.net/sometime-php/2008/12/http_build_query/

投稿2017/09/19 18:15

kei344

総合スコア69407

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

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

m.ts10806

2017/09/20 01:21 編集

kei344さん 質問者は幾つか聞きたいことがあるようなので、どれに対する回答かを明記した方が良いと思います。
kei344

2017/09/20 02:11

To: luckerさん To: mts10806さん 編集される前の元の質問は「また、」及びその以前の部分がなかったので、この回答です。 https://teratail.com/questions/history-questions/93160 > 詳細ページへのGETである?idとページネーションへのGETである?pageを両立するにはどうすればよいでしょうか?
kei344

2017/09/20 02:12

あれ、コメント消えてる?
m.ts10806

2017/09/20 02:18

なるほど、了解です。確かに当該部分が追加されてますね。 履歴見落としてました。失礼しました。
kei344

2017/09/20 02:24

いえ、質問文が変わっていることに気づいていなかったので、指摘いただけて助かります。
退会済みユーザー

退会済みユーザー

2017/09/20 03:11 編集

そういうことすか。ならマイナス評価だけは戻しておきますけど、どのみち、クエリーストリングについて仕組みを全く説明しないのは結局、僕的にはやっぱり回答になってない評価です。 質問者が知りたかったのって、そこんとこでしょう?
kei344

2017/09/20 05:52

To: luckerさん 評価はどちらでも良いですよ。指摘の伴ったマイナス評価は自分の回答を見直す良い機会になりますので。確かにご指摘の通り、説明なくURLを例示しhttp_build_queryの参考URLを提示しているだけなので、丁寧な回答ではありませんね。 「質問者が知りたかったの」がおわかりになるのであれば、回答をされてはいかがでしょう。
退会済みユーザー

退会済みユーザー

2017/09/20 06:21

だって、僕が回答すると喜々としてマイナス評価つける勢力がいるんですもん。
m.ts10806

2017/09/20 06:26 編集

最終的に回答の評価をするのは質問者です。もちろん分かりやすく丁寧な(言葉を使った)回答を心がけるのは当然ですが。 luckerさんは低評価つくのは気にしない方のようなので、気にせず回答されては? 回答者にあれこれ指摘してばかりなのは問題解決に向かわないので良くないと思います。 既に本回答で複数回、回答するよう促されている意味を考えてみてくださいね。
kei344

2017/09/20 06:27

> 僕が回答すると喜々としてマイナス評価つける勢力がいるんですもん それは残念な状況ですね・・・。 質問本文がまた変わったので、クエリーストリングについては質問者にとってどうでもよいことになったようです・・・。また何か有ればご指摘ください。よろしくお願いします!
gsuisk

2017/09/20 06:50

皆様、お騒がせして本当にすみませんでした...反省します。
gsuisk

2017/09/20 06:51

Kei344さんのご回答も参考になったので高評価させていただきます。
guest

0

こんにちは。

ソースを見ていないので推測で申し訳ないですが、
CSRFのトークンはhiddenで渡すとありますので、CSRFチェック処理ではPOSTとして受け取ることを期待しているのではないでしょうか?
(POSTは、formタグで括られていてinputタグのパラメータをsubmitボタンで送るやつですね)

それにもかかわらず、ページングの「次ページ」等はリンク(aタグ)になっていてGETとして
送られ、POST値であるCSRFのトークンがサーバに送られていないということかなと思います。

解決するには、CSRFのチェック処理でPOST値、GET値の両方から取得できるようにして、
ページングのリンクのクエリーにトークンを含めるといいと思います。

投稿2017/09/20 06:52

s-washion

総合スコア204

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

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

0

検索条件を引き継ぐためには、条件内容である$_POSTの値+ページ番号という形でページ遷移する必要があります。

現状はページ切り替えのときにページ数しか渡していないため、条件がリセットされています。

投稿2017/09/19 21:50

編集2017/09/19 21:50
rkojima

総合スコア421

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

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

退会済みユーザー

退会済みユーザー

2017/09/19 22:10

聞かれていることと、なんか違うような…
rkojima

2017/09/19 22:26

あ、データ件数の取得にwhere句が抜けているため全件数でページ数計算してしまってるところ。ですかね。。 失礼しました。 $page_num = $pdo->prepare(" SELECT COUNT(*) id FROM table "); この部分にも、データ取得時と同じwhereの指定が必要です。 lukerさんご指摘ありがとうございました。 問題点も理解されているようなので、間違っている部分を指摘していただけると問題解決につながり助かります。m()m
退会済みユーザー

退会済みユーザー

2017/09/19 22:35

正直、僕も何聞かれてるのかよく分かん無いんですけどね…
退会済みユーザー

退会済みユーザー

2017/09/19 22:43

なんとなくだけど、 詳細ページで  検索結果順位(もしくはページ)/検索結果数みたいにだそうとしてる気もしないでもない。 lucker さんがわかってるようなので間違え?を指摘せずに自分で回答すればいいかも
退会済みユーザー

退会済みユーザー

2017/09/19 22:47

いや、マジでよく分かんないんですよ。二人の回答分については、まぁ、それも質問だろうと思うんですけど、上の方に何を言ってるのかよく分からないトラブル事項も書いてあって、だから様子見してるんです。 仕事とかでもそうですけど、不明事項があるのに適当に判断して手をつけちゃうのは事故の元ですし。
gsuisk

2017/09/20 06:06

勘違いしていた部分が多く、見当違いな質問をしてしまい本当にすみませんでした。質問を改めたので、もしよければ読んでいただければと思います。
guest

0

自己解決

お騒がせして申し訳ありませんでした。

最初に質問したことはページ機能にGETを使うが、他のGETリクエストと両立はどうするのかということでした。

これは完全に私の勘違いで、見当違いな質問でした。(別に両立しているわけではありませんでした)

ページ数についてはご指摘の通り、WHERE句に検索条件と同じものを記述すれば解決できました。

CSRFについては別質問にすべきことであったので、ここでは上記の2点が解決したことを伝えます。

皆様本当にすみませんでした。

投稿2017/09/20 06:47

gsuisk

総合スコア72

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問