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

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

ただいまの
回答率

89.71%

PHPでの検索フォームでの作成

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 928
退会済みユーザー

退会済みユーザー

 前提・実現したいこと

検索フォームに入力した文字と一致するデータをDBから出力し、表示するページを作成しています。

検索を行い一致したデータが5件以上だった場合、

複数ページに分けた表示をを行いたいと思っています。

自力調べ途中まで実行してみたのですが、

上手くいかないのでアドバイスいただきたいと思っています。

<現在の状況>

検索ワードを入力するとデータから5件を抽出して表示し表示することはできています。

<これから実施したいこと>

次へ・前へなどのページ送りを作成し、データを5件づつ表示

次に何をすればよいのか、具体的にどのような処理が足りないのか、教えていただきたいです。

php初心者で手探りで実施している状態なので、わかりやすく教えていただければと思います。
DBはpostgreSQLを使用しています。

※コードは全体だと非常に長いので、関係のありそうな場所だけ抜粋しています。

 該当のソースコード

//php部分
session_start();
$connect = "host=$P_IP port=$P_PORT dbname=$P_DBNAME user=$P_DBUSER password=$P_DBPASS";

if (! $con = pg_connect( $connect ) ){
    die( 'Postgres接続失敗' );
  } 
$KEY = $_POST['word'];
$KEY1 = $_POST['word1'];
$KEY2 = $_POST['word2'];
$KEY3 = $_POST['word3'];

if($_SERVER["REQUEST_METHOD"] === "POST"){
  $_SESSION['word'] = $_POST['word'];
  $_SESSION['word1'] = $_POST['word1'];
  $_SESSION['word2'] = $_POST['word2'];
  $_SESSION['word3'] = $_POST['word3'];
}



$word3 = "";
if(array_key_exists("word3",$_SESSION) && !empty($_SESSION["word3"])){
    $word3 = $_SESSION['word3'];
}
$where = "";
if(count($where_list) > 0){
   $where = " where ".implode(" and ",$where_list); 
}
$sql = "SELECT * FROM theme ".$where;
$result = pg_query($con,$sql);

if (!isset($_GET['page'])) {
    $page = 1; // 最初のアクセス
} else {
    $page = intval($_GET['page']); // ページ指定でのアクセス
    if ($page == 0 ) { die('page no error'); }
}

$offset = ($page-1) * 5;

$result = pg_query($con, "SELECT * FROM theme WHERE(theme_ans LIKE '%{$KEY3}%') OR (theme_que LIKE '%{$KEY3}%')limit 5 offset $offset");


 //html部分

 <form  method="post" action='<?= $PHP_SELF ?>'>
     <p1>製品種別</p1>
     <select class="soft_select" name="word1">
                  <option value="0" name="word1" >0.全て</option>
                        <option value="1" name="word1" >1.</option>
                        <option value="2" name="word1" > 2.</option>
                         <option value="3" name="word1" >3.</option>
                  <option value="3" name="word1" >4.</option>
                   
     </select>
     <p1>質問種別</p1>
     <select class="type_select" name="word2">
                       <option value="0" name="word2" >0.全て</option>
                        <option value="1" name="word2"  >1.</option>
                        <option value="2" name="word2" > 2.</option>
                         <option value="3" name="word2" >3.</option>
                        <option value="4" name="word2" >4.</option>
                         <option value="5" name="word2" >5.</option>
      </select> <p1>ワード</p1>


    <input type="text" name="word3" id="">
    <input type="submit" value="検索">
  </form>
     <p><a href="user669.php?page=<?php echo ($page + 1); ?>&<?php echo $word3;?>"action='<?= $PHP_SELF ?>';>next</a></p>
     <p><a href="user669.php?page=<?php echo ($page - 1); ?>&<?php echo $word3;?>">back</a></p>
  </div>



<table>
      <tr>
        <th class="type_q">製品種別</th>
        <th class="contents">質問種別</th>
        <th class="question">問い合わせ内容</th>
        <th class="answer">回答</th>
      </tr>

 <?php
    if (empty($KEY3)) {  } else {
    for ($i = 0 ; $i < pg_num_rows($result) ; $i++){
    $rows = pg_fetch_array($result, NULL, PGSQL_ASSOC);
    print '<tr>';
    print'<th class="type_q">'.($rows['type_que']).'</th>';
    print'<th class="contents">'.($rows['theme_id']).'</th>';
    print'<th class="question">'.($rows['theme_que']).'</th>';
    print'<th>'.($rows['theme_ans']).'</th>';
    print '</tr>';
    }
    }
?></table> 
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • m.ts10806

    2018/06/18 14:51

    minnnnnさん 追記されたに伴い回答に追記しました。ご確認お願いします。今回の対応するにつき、結構基本的なところの理解が抜けている印象を受けました。今回ついた回答でどこまで参考になるか分かりませんが、それぞれの処理の意味や意図をきちんと理解し「分かった気」にならないように着実に身につけてください。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2018/06/18 21:17

    解答ありがとうございます。ご指摘のとおり、初心者なのに、1から学ぶというよりは、この機能をつくりたいから調べてみるというのを繰り返しま断片的な知識のまま作成して居るので、基本的な部分が抜けているのだと思います。なので、追記内容含めてそのようなご指摘頂けてありがたいです。

    キャンセル

  • m.ts10806

    2018/06/21 21:27

    解決済みとされたようですが、最終的にどのように解決されたかも書いてください。 https://teratail.com/help/question-tips#questionTips4-2 >解決したら、どのアドバイスを元にどのように解決したのかを「回答へのコメント」や「質問への追記」で書き残し、回答してくれたユーザーへのフィードバックをしましょう。

    キャンセル

回答 2

+2

さーてっと、そうしたら…だ。

コードをざっと見ると、クエリーストリングでページの指定はできるようになってるみたいだね。このpage=のとこ。

<a href="https://portal.egg-net.co.jp/egg/user/user669.php?page={$back}">

ということは、後は検索ワードが保持できればいいだけだ。

やり方は2つ。

1.pageと同じように、word, word1, word2, word3についても、クエリーストリングで持ち回す。

コード的には今は$KEY3(word3)しか検査しないようになってるからそれで書くと、

<a href="https://portal.egg-net.co.jp/egg/user/user669.php?page={$back}&word3={$KEY3}">

みたいな話だね。

2.セッションに検索ワードを保存してしまう。

こっちは結構話が長くなる。

どっちもありっていえばありだけど、検索ワードが漏れても困らないなら1の方がいいのかな。ま、とりあえずやってみよう。

追記

んーで、あとはリンクにページ番号を付与する。

 <p><a href="https://portal.egg-net.co.jp/egg/user/user669.php?page={$page++}">next</a></p>
 <p><a href="https://portal.egg-net.co.jp/egg/user/user669.php?page={$page--}">back</a></p>

みたいにね。

そうすっと、今1ページだったら 0ページになっちゃったり、データ10件しか無くて2ページ目に居るのに++して存在しない3ページ目を取りに行こうとしちゃったりになるから、今度はそこを対処するわけ。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/18 13:41

    教えていただいたとおりに実施しました。nextをクリックした際に、die('page no error');というエラーがかえってきてしまいます。リンクも、={$page++}のままです。これは、ページ数に++するという処理がされていないということでしょうか?

    キャンセル

  • 2018/06/18 14:08

    現在のコードを質問に追記された方が良いかと。

    キャンセル

  • 2018/06/18 14:20

    なんどもすみません。現在のコードに修正しました。ページ送りとWordの保存は実施できるようになりました。back/nextをクリックすると(URLに、page=現在のページ番号&word3が表示される状態)。
    ただ、back/next をクリックすると、
    $result = pg_query($con, "SELECT * FROM theme WHERE(theme_ans LIKE '%{$KEY3}%') OR (theme_que LIKE '%{$KEY3}%')limit 5 offset $offset");
    が実行されていないのか、DBの結果が表示されません。何が原因でしょうか?

    キャンセル

checkベストアンサー

0

ある程度のヒントが回答で出ているのでそれ以外での気づきを。
SQLのoffsetがミスっています。

offsetは「取得する1件目のスタート位置」を指定するものです。
ちなみにデータの1件目は「0(ゼロ)」なので、デフォルト$pageを1として
そのままoffsetに指定している時点で本来の1件目が取得できていません。
今の状態だとページ2がきたときに3件目から8件目を取得していることになります。
(ページ3の場合は4件目から9件目)

つまり、
ページが1の場合は0、2の場合は+1ページ表示分の件数でないといけません。

上記を踏まえてoffsetについては下記のような計算で出すこととなります。

$offset = ($page-1) * {1ページ表示件数};

参考まで。

 追記

session_start()は基本的に何かの出力前に書くべきものです。

クッキーに基づくセッションを使用している場合、ブラウザに何か出力を行う前に session_start() をコールする必要があります。

ファイル冒頭で宣言しましょう。
また、おそらく画面にエラー出力してないですよね?
下記のようにベタで書いてあると、GETアクセスの場合、必ずエラーが出ます。

$KEY = $_POST['word'];
$KEY1 = $_POST['word1'];
$KEY2 = $_POST['word2'];
$KEY3 = $_POST['word3'];


基本的にはエラー表示はOnにしておきましょう。

で、上記を踏まえますと、「DBの結果が表示されません」の理由が分かります。

下記のようなつくりになっていますが、ページ送りのリンクでアクセスした際は必ずGETでのアクセスとなります。

$KEY = $_POST['word'];
$KEY1 = $_POST['word1'];
$KEY2 = $_POST['word2'];
$KEY3 = $_POST['word3'];
$_SESSION['word3'] =$KEY3;

ということは$_POSTはそもそも存在しません。
おそらくNULLになっているんじゃないかと(試したわけではないですが)

ということは上記は「POSTのときのみ実行する」ようにしなければなりません。

if($_SERVER["REQUEST_METHOD"] === "POST"){
  $KEY = $_POST['word'];
  $KEY1 = $_POST['word1'];
  $KEY2 = $_POST['word2'];
  $KEY3 = $_POST['word3'];
  $_SESSION['word3'] =$KEY3;
}

というかおそらく使わない変数が増えてくるのでむしろこうでもいい。

if($_SERVER["REQUEST_METHOD"] === "POST"){
  $_SESSION['word'] = $_POST['word'];
  $_SESSION['word1'] = $_POST['word1'];
  $_SESSION['word2'] = $_POST['word2'];
  $_SESSION['word3'] = $_POST['word3'];
}

で、あとは、SESSIONに値が存在するか確認して受け取る
※ひとまずword3のみ。他も同じ。

$word3 = "";
if(array_key_exists("word3",$_SESSION) && !empty($_SESSION["word3"])){
    $word3 = $_SESSION['word3'];
}


あとは$word3が空じゃないときにSQLにセット。
※複数条件の場合も$where_listに追加でいけるはず
例:

$where_list = [];
if($word3 !== ""){
  $where_list[] = " ( (theme_ans LIKE '%{$word3}%') OR (theme_que LIKE '%{$word3}%') ) ";
}
$where = "";
if(count($where_list) > 0){
   $where = " where ".implode(" and ",$where_list); 
}
$sql = "SELECT * FROM theme ".$where;
$result = pg_query($con,$sql);

※本来はSQLのエスケープも入れるべきですが、省略しています。

 更に追記 2018/6/19 14:20

検索部分 ※session_start()部分、DB接続部分は除く

if($_SERVER['REQUEST_METHOD'] === "POST"){
    $_SESSION['word'] = $_POST['word'];
    $_SESSION['word1'] = $_POST['word1'];
    $_SESSION['word2'] = $_POST['word2'];
    $_SESSION['word3'] = $_POST['word3'];
}

if (!isset($_GET['page'])) {
    $page = 1; // 最初のアクセス
} else {
    $page = intval($_GET['page']); // ページ指定でのアクセス
    if ($page == 0 ) { die('page no error'); }
}

$offset = ($page-1) * 5;

//検索条件
$where = "";

if(isset($_SESSION)){
    $word3 = "";
    if(array_key_exists("word3",$_SESSION) && !empty($_SESSION["word3"])){
        $word3 = $_SESSION['word3'];
    }
    $where_list = [];
    if($word3 !== ""){
        $where_list[] = " ( (theme_ans LIKE '%{$word3}%') OR (theme_que LIKE '%{$word3}%') ) ";
    }
    $where = "";
    if(count($where_list) > 0){
        $where = " where ".implode(" and ",$where_list);
    }
}


$sql = "SELECT * FROM theme ".$where. " limit 5 offset ".$offset;
$result = pg_query($con,$sql);

$sqlの出力結果例:
word3に何もない場合

SELECT * FROM theme limit 5 offset 0


word3にaと入力された場合

SELECT * FROM theme where ( (theme_ans LIKE '%a%') OR (theme_que LIKE '%a%') ) limit 5 offset 0

まず確認しなければならないのは「想定通りのデータを取得できるSQLができているかどうか」です。
$sqlをechoで画面出力してみるなり何なりして、PHPからではなくPostgreSQLであればPgAdminなどのツールで直接DBに対して取得したSQLを実行してみると良いです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/19 14:07

    ご指摘ありがとうございます。本当におっしゃる通りなので、理解できるように勉強していきたいと思います。

    現状、更新したものと同じものをサーバーにあげてみたところ、DB検索ができない。5件ずつ表示したい以前に結果が出力されない状況です。

    キャンセル

  • 2018/06/19 14:19

    そもそも
    SELECT * FROM theme WHERE(theme_ans LIKE '%%') OR (theme_que LIKE '%%')limit 5 offset 0
    のような形となっているので何もヒットしない状態なんじゃないかと思いますけど・・

    キャンセル

  • 2018/06/19 14:22 編集

    「検索部分」としてコード追記しました。
    動作未検証ですが、文法エラーは無くおおよそ問題の無いと思われるSQL文ができあがるはずです。

    ただ、html部分の$PHP_SELFがなおっていませんし、aタグに入っているaction属性は意味がないはずですし、
    最後の部分↓の分岐が何をしたくて入れているのか分かりません。その部分は適宜調整してください。
    if (empty($KEY3)) { } else {

    キャンセル

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

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