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

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

ただいまの
回答率

89.64%

複数あいまい検索をしたい

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 2,311

tukimi

score 10

前提・実現したいこと

PHPとzammpを使ってます。
あらかじめ、データベースに登録しておいた情報をあいまい検索したいのですが、上手くいきません。
あと○○年~○○年と指定して、検索すると○○年~○○年までの情報が出るようにしたいのです。
以下のソースはbooknameにポストされたものをあいまい検索するものです。
どうsql文を繋げて三つの欄を検索出来るようになるのか、ご教示お願い致します。

発生している問題・エラーメッセージ

Notice: Undefined variable: errors in C:\xampp\htdocs\book\bookSearch.php on line 14
Notice: Undefined variable: errors in C:\xampp\htdocs\book\bookSearch.php on line 82

該当のソースコード

//検索ワード入力画面
<form action="bookSearch.php" method="post">
<table>
<tr>
<td>題名 :</td>
<td><input type="text" name="bookname"></td>
</tr>
<tr>
<td>著者 :</td>
<td><input type="text" name="writer"></td>
</tr>
<tr>
<td>出版年:</td>
<td><input type="text" name="year">~</td><td><input type="text" name="year2"></td>
</tr>
</table>
<input type="submit" value="検索">
<input type="reset" value="リセット">
</form>

//検索先
<?php
header("Content-type: text/html; charset=utf-8");

if(empty($_POST)) {
header("Location: book_up.php");
exit();
}else {
//名前入力判定
if(!isset($_POST['bookname']) || $_POST['bookname'] ===""){
$errors['bookname'] = "題名が入力されていません。";
}
}

if(count($errors) === 0){

$dsn ='mysql:host=localhost;dbname=book;charset=utf8';
$user='root';
$password='';

try{
$dbh = new PDO($dsn,$user,$password);
$statement = $dbh->prepare("SELECT * FROM hondana WHERE bookname LIKE (:bookname) ");

if($statement){
$bookname = $_POST['bookname'];
$like_bookname="%".$bookname."%";
$statement->bindValue(':bookname', $like_bookname, PDO::PARAM_STR);

if($statement->execute()){
$row_count = $statement->rowCount();
while ($row = $statement->fetch()) {
$rows[]= $row;
}
}

else {
$errors['error'] = "検索失敗しました。";
}
$dbh = null;
}
}

catch (PDOException $e){
print('Error:'.$e->getMessage());
$errors['error'] = "データベース接続失敗しました。";
}
}

?>
<!DOCTIPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<h2>図書検索について</h2>
図書を登録できます。
<p>図書検索フォーム</p>

<?php if (count($errors) === 0): ?>

<p>【<?=htmlspecialchars($bookname,ENT_QUOTES, 'UTF-8')."】で検索しました。"?></p>
<p><?=$row_count?>件です。</p>

<table rules="all" border="1">
<tr><td>id</td><td>name</td></tr>

<?php
foreach($rows as $row){
?>
<tr>
<td><?=$row['code']?></td>
<td><?=htmlspecialchars($row['bookname'],ENT_QUOTES,'UTF-8')?></td>
<td><?=htmlspecialchars($row['writer'],ENT_QUOTES,'UTF-8')?></td>
<td><?=htmlspecialchars($row['year'],ENT_QUOTES,'UTF-8')?></td>
</tr>
<?php
}
?>

<?php elseif(count($errors) > 0): ?>
<?php
foreach($errors as $value){
echo "<p>".$value."</p>";
}
?>
</table>
<?php endif; ?>

<a href="book_up.php">戻る</a>

</body>
</html>

試したこと

課題に対してアプローチしたことを記載してください

補足情報(言語/FW/ツール等のバージョンなど)

より詳細な情報

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • tukimi

    2017/07/04 17:55

    miyahanさん>見づらくてすみません。PHPは初心者なもので、どの辺りでインデントをすればいいのか分からないのです。

    キャンセル

  • tukimi

    2017/07/04 17:55

    kei344さん>分かりました、やってみます

    キャンセル

  • kei344

    2017/07/05 10:51

    まだ質問が「受付中」になっていますが、いったん「解決済」にされてはいかがでしょうか。また、解決されていないなら状況を質問文に追記ください。

    キャンセル

回答 2

checkベストアンサー

0

とりあえず、動くものをサンプルとして提示します。

検索フォーム(ソースにコメントもしていますが、Centerタグはやめましょう…)

<!DOCTYPE html>
<html>
   <head>
      <title>A.php</title>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   </head>
   <body>
       <!--centerタグはやめましょう…-->
       <div style="text-align:center">
           <form action="bookSearch.php" method="post">
              <table style="margin: 0px auto;">
                  <tr style="border: solid">
                      <td>題名 :</td>
                      <td><input type="text" name="bookname"></td>
                  </tr>
                  <tr>
                      <td>著者 :</td>
                      <td><input type="text" name="writer"></td>
                  </tr>
                  <tr>
                      <td>出版年:</td>
                      <td><input type="text" name="year">~</td>
                      <td><input type="text" name="year2"></td>
                  </tr>
              </table>
              <input type="submit" value="検索">
              <input type="reset" value="リセット">
          </form>
       </div>
</body>
</html>

で、検索のフォームです。
まずは、yambejp様の指摘通り、質問文のエラーは$errorsが定義されていないよ!というものです。
その為、初期化しておきましょう。
次に、

検索すると○○年~○○年までの情報が出るようにしたいのです

という部分ですが、日付入力の有無を見て、SQLを動的に組み立てれば良いのではないかと思います。

<?php
header("Content-type: text/html; charset=utf-8");
$errors=array();//ここで$errorsを初期化!
if(empty($_POST)) {
    header("Location: book_up.php");
    exit();
}else {
    //名前入力判定
    if(!isset($_POST['bookname']) || $_POST['bookname'] ===""){
        $errors['bookname'] = "題名が入力されていません。";
    }
}

if(count($errors) === 0){
    $dsn ='mysql:host=localhost;dbname=test;charset=utf8';
    $user='test';
    $password='test';
    try{
        $dbh = new PDO($dsn,$user,$password);
        $sql = "SELECT * FROM hondana ";
        $sql .= "WHERE bookname LIKE :bookname ";
        //Validationはかけて下さいね…(今回はFromがあれば必ずToがある前提です。)
        if($_POST['year']){
            $sql .= "And year >= :year and year <= :year2";
        }
        $statement = $dbh->prepare($sql);
        if($statement){
            $statement->bindValue(':bookname', "%".$_POST['bookname']."%", PDO::PARAM_STR);
            if($_POST['year']){
                $statement->bindValue(':year', $_POST['year'], PDO::PARAM_INT);
                $statement->bindValue(':year2', $_POST['year2'], PDO::PARAM_INT);
            }
            if($statement->execute()){
                $row_count = $statement->rowCount();
                while ($row = $statement->fetch()) {
                    $rows[]= $row;
                }  
            }else {
                $errors['error'] = "検索失敗しました。";
            }
            $dbh = null;
        }
    }catch (PDOException $e){
        print('Error:'.$e->getMessage());
        $errors['error'] = "データベース接続失敗しました。";
    }
}
?>
<!DOCTIPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <h2>図書検索について</h2>
        図書を登録できます。
        <p>図書検索フォーム</p>
            <?php if (count($errors) === 0): ?>
        <p>【<?=htmlspecialchars($_POST['bookname'],ENT_QUOTES, 'UTF-8')."】で検索しました。"?></p>
        <p><?=$row_count?>件です。</p>
        <table rules="all" border="1">
            <th><tr><td>id</td><td>name</td></tr></th>
            <?php foreach($rows as $row){ ?>
                <tr>
                    <td><?=$row['code']?></td>
                    <td><?=htmlspecialchars($row['bookname'],ENT_QUOTES,'UTF-8')?></td>
                    <td><?=htmlspecialchars($row['writer'],ENT_QUOTES,'UTF-8')?></td>
                    <td><?=htmlspecialchars($row['year'],ENT_QUOTES,'UTF-8')?></td>
                </tr>
            <?php } ?>
            <?php elseif(count($errors) > 0): ?>
                <?php
                    foreach($errors as $value){
                        echo "<p>".$value."</p>";
                    }
            ?>
    </table>
<?php endif; ?>

<a href="book_up.php">戻る</a>

</body>
</html>

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/05 15:17

    エラーもなくなり、無事動きました!
    ありがとうございました。

    キャンセル

0

コメント「//名前入力判定」の後ろあたりに

$errors=[];


をいれて、$errors自体を初期化しておいてください

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/04 17:37

    ありがとうございます!
    エラーがなくなりました。

    キャンセル

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

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