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

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

ただいまの
回答率

87.61%

PHP:検索フォーム

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 450

score 8

DBに登録している商品を検索かけて、表示させたいです。
商品IDや名前を検索かけると表示はされるのですが、適当な値をいれても、データを取り出せてしまいます。もしかしたら、どこかのコードでとりあえず出力するようになってしまっているのかと・・・原因がつかめないためお力を貸してほしいです。

  $hoge1 = $_POST['number']??''; // 商品番号
    $hoge2 = $_POST['name']??''; //商品名
    $hoge3 = $_POST['date']??''; // 入荷日
    if(empty($hoge1) && empty($hoge2) && empty($hoge3)){ // 初期状態を空白
        $sql = $pdo->query('SELECT * FROM items where id=0');
    // 条件が一つでも入力されていれば検索をかけれるようにする
    }elseif($sql=$pdo->query('SELECT * FROM items WHERE 1=1'));{
    if($hoge1 ){'AND number=:number';
    }
    if($hoge2 ){'AND name=:name';
    }
    if($hoge3 ){'AND date=:date';
    }
    }
    $rows = $sql->fetchAll();

初期表示を空にするため

if(empty($hoge1) && empty($hoge2) && empty($hoge3)){ // 初期状態を空白
        $sql = $pdo->query('SELECT * FROM items where id=0');

検索条件は、一つでも当てはまっていれば表示する

// 条件が一つでも入力されていれば検索をかけれるようにする
    }elseif($sql=$pdo->query('SELECT * FROM items WHERE 1=1'));{
    if($hoge1 ){'AND number=:number';
    }
    if($hoge2 ){'AND name=:name';
    }
    if($hoge3 ){'AND date=:date';
    }
    }

テーブルのコード

<tbody>

                        <?php foreach ($rows as $key => $row): ?>
                            <tr data-index="0">
                                <th scope="row">
                                    <!-- 1-2: #ラジオボタン -->
                                    <input class="form-check-input ml-1" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
                                    <label class="form-check-label" for="flexRadioDefault1"></label>
                                </th>
                                <td><?= $row['number']?></td>
                                <td><?= $row['name']?></td>
                                <td><?= $row['date']?></td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
<form method = "post" action = "hogehoge.php" name="test">
                        <div class="form-group">
                            <div class="row">
                                <div class="col-4">
                                    <label for="number" class="control-label">商品番号:</label>
                                    <input type="number" class="form-control" id="number" name="number" value="">
                                </div>
                                <div class="col-4">
                                    <label for = "name" class = "control-label">商品名:</label>
                                    <input type = "text" class = "form-control" id = "name" name = "name" value="">
                                </div>
                                <div class="col-4">
                                    <label for = "date" class = "control-label">入荷日:</label>
                                    <!-- input="date"でカレンダー表示 -->
                                    <input type="date" class="form-control" id="date" name="date" placeholder="年/月/日" value="">
                                </div>
                            </div>
                            <!-- 2-1:クリア処理 ボタン:「クリア」・「検索」-->
                            <div class="form-group text-right mt-3">
                                <button class="btn btn-warning btn-sm" type="reset" name="reset" value="clear">クリア</button>
                                <button class="btn btn-info btn-sm" type="serch">検索</button>
                            </div>
                        </div>
                    </form>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • 退会済みユーザー

    退会済みユーザー

    2021/06/03 11:29 編集

    「if(empty($hoge1 && empty($hoge2) && empty($hoge3))」 でカッコが足りてない。転記ミスはほかにないですか? あと、ソースまるごと貼ってくれないと、第三者が再現できないので、エスパー的回答に終止するしかないんですけど。

    キャンセル

回答 3

+2

if(empty($hoge1 && empty($hoge2) && empty($hoge3))


if(empty($hoge1) && empty($hoge2) && empty($hoge3))


くらいはパット見でわかった。


    if(empty($hoge1 && empty($hoge2) && empty($hoge3)){ // 初期状態を空白
        $sql = $pdo->query('SELECT * FROM items where id=0');
    // 条件が一つでも入力されていれば検索をかけれるようにする
    }elseif($sql=$pdo->query('SELECT * FROM items WHERE 1=1'));{


elseifのところ、おかしいよな?


    if($hoge1 ){'AND number=:number';
    }
    if($hoge2 ){'AND name=:name';
    }
    if($hoge3 ){'AND date=:date';
    }


何がしたいの? 文字列リテラルだけ置いても意味がない。

ダメ出しばかりしているのは、仕様や設計に関わる情報が質問文中にないために、
どう改善すればいいかを考える段階にないってことです。
思考整理中に試しに実行したコードのまま、動作確認すら取ってないのかなって思えるほど、
phpコードからやりたいことが読み取れないので。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

  }elseif($sql=$pdo->query('SELECT * FROM items WHERE 1=1'));{

ここ、最初のifを満たさなければ必ず実行されてます。

  if($hoge1 ){'AND number=:number';
}
if($hoge2 ){'AND name=:name';
}
if($hoge3 ){'AND date=:date';
}

ここ、なんにもしてません。

SQLを動的に組み立てたいのでしょうけど、
これでは組み合わせの検索ができませんので、
配列に追加していってimplodeでandで結合すると良いです。

また、たとえ条件いれてもパラメータセットしててバインドしてないのでエラーになるのでは(ちゃんとtry-catchしてね)

いずれにしても下記のような記事は読んで、基本的な概念や組み方は覚えましょう。

PHPでデータベースに接続するときのまとめ

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

checkベストアンサー

0

<?PHP
$number=filter_input(INPUT_POST,'number');
$name  =filter_input(INPUT_POST,'name');
$date  =filter_input(INPUT_POST,'date');
$data  =[];
$sql='SELECT * FROM items where 1 ';
if(count(array_filter([$number,$name,$date],function($x){
  return !empty($x);
}))==0){
  $sql.=" and 0";
}
foreach(["number","name","date"] as $val){
  if($$val){
    $sql.=" and {$val}=?";
    $data[]=$$val;
  }
}
print $sql.";<br>\n";
print_r($data);
?>
<hr>
<form method="post">
number:<input name="number" value=""><br>
name:<input name="name" value=""><br>
date:<input name="date" value=""><br>
<input type="submit" value="send">
</form>


※一部フローを調整

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2021/06/03 18:26

    m.ts10806様のおっしゃる通り、まだまだ私にはこのコードが理解できない状態です。
    if(count(array_filter([$number,$name,$date],function($x){
    return !empty($x);
    }))==0){
    $sql.=" and 0";
    }
    foreach(["number","name","date"] as $val){
    if($$val){
    $sql.=" and {$val}=?";
    $data[]=$$val;
    }
    }

    ここの部分でどういう動きになっているのか、よければご教授下さい。

    キャンセル

  • 2021/06/03 19:33

    まず最初のifと、あとのforeachは独立してますので順に解説
    array_filter([$number,$name,$date],function($x){
    return !empty($x);
    })
    は、$numberと$nameと$dateのそれぞれから空でないものを抽出しています
    それをcountしてるので空でない個数で、それが==0なのですから
    ifの条件分は「すべてが空」という意味です。
    その時、$sql文にand 0がつき、where 1 and 0となります
    SQLの抽出条件としてはand 0は常に偽となるためSQLは必ず空を返します

    foreachの方は、"number","name","date"という文字列をそれぞれ取り出して$valに入れて
    ループ処理をします
    仮に"number"を$valにわたすとif($$val)というのはif($number)と同等なので
    $numberが空ではない場合という条件になります
    SQL文には" and number=?"という文字が追加され、$dataに$numberを追加します
    これをnameやdateについても続けます。

    あとは私の回答をご自身の環境でコピペしてnumber、name、dateの入力欄に
    値を入れたり、入れなかったりしてサブミットすると
    どういう処理がされるかわかると思います。

    なお最終的に$sqlはprepareを使って実行され、その値は$dataをexecuteするとよいでしょう

    キャンセル

  • 2021/06/16 15:13

    大変詳しいアドバイスありがとうございます!
    おかげさまで、見事に実装することできました。
    やはり、基礎からやり直してみたいと思います。
    今後とも何卒ご教授いただければ幸いです!!

    キャンセル

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

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

関連した質問

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