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

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

ただいまの
回答率

90.34%

  • PHP

    21402questions

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

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

解決済

回答 4

投稿 編集

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

gsuisk

score 64

追記です。

わかりづらい質問をしてしまい、すみませんでした。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を両立するにはどうすればよいでしょうか?
教えていただけたら幸いです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • gsuisk

    2017/09/20 15:49

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

    キャンセル

  • mts10806

    2017/09/20 16:05

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

    キャンセル

  • mts10806

    2017/09/20 16:06 編集

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

    キャンセル

回答 4

+5

http_build_query 使えばよいのでは。

https://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/20 10:20 編集

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

    キャンセル

  • 2017/09/20 11:11

    To: luckerさん
    To: mts10806さん
    編集される前の元の質問は「また、」及びその以前の部分がなかったので、この回答です。

    https://teratail.com/questions/history-questions/93160
    > 詳細ページへのGETである?idとページネーションへのGETである?pageを両立するにはどうすればよいでしょうか?

    キャンセル

  • 2017/09/20 11:12

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

    キャンセル

  • 2017/09/20 11:18

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

    キャンセル

  • 2017/09/20 11:24

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

    キャンセル

  • 2017/09/20 12:11 編集

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

    キャンセル

  • 2017/09/20 14:52

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

    キャンセル

  • 2017/09/20 15:21

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

    キャンセル

  • 2017/09/20 15:25 編集

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

    キャンセル

  • 2017/09/20 15:27

    > 僕が回答すると喜々としてマイナス評価つける勢力がいるんですもん
    それは残念な状況ですね・・・。

    質問本文がまた変わったので、クエリーストリングについては質問者にとってどうでもよいことになったようです・・・。また何か有ればご指摘ください。よろしくお願いします!

    キャンセル

  • 2017/09/20 15:50

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

    キャンセル

  • 2017/09/20 15:51

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

    キャンセル

+1

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

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

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/20 07:10

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

    キャンセル

  • 2017/09/20 07:26

    あ、データ件数の取得にwhere句が抜けているため全件数でページ数計算してしまってるところ。ですかね。。

    失礼しました。

    $page_num = $pdo->prepare("
    SELECT COUNT(*) id
    FROM table
    ");

    この部分にも、データ取得時と同じwhereの指定が必要です。

    lukerさんご指摘ありがとうございました。
    問題点も理解されているようなので、間違っている部分を指摘していただけると問題解決につながり助かります。m()m

    キャンセル

  • 2017/09/20 07:35

    正直、僕も何聞かれてるのかよく分かん無いんですけどね…

    キャンセル

  • 2017/09/20 07:43

    なんとなくだけど、 詳細ページで  検索結果順位(もしくはページ)/検索結果数みたいにだそうとしてる気もしないでもない。

    lucker さんがわかってるようなので間違え?を指摘せずに自分で回答すればいいかも

    キャンセル

  • 2017/09/20 07:47

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

    仕事とかでもそうですけど、不明事項があるのに適当に判断して手をつけちゃうのは事故の元ですし。

    キャンセル

  • 2017/09/20 15:06

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

    キャンセル

+1

こんにちは。

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

check解決した方法

0

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

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

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

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

同じタグがついた質問を見る

  • PHP

    21402questions

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