[php+SQL]複数カラムに対して複数ワード対応のデータベース検索フォームを作る

疲れた。

類似記事

こうする

検索したら同じページに結果を出力するタイプのものを作るとする。

<?php
if(empty($_GET['searchword'])){
    $searchword = '';
}else{
    $searchword = $_GET['searchword'];
    $searchword = str_replace(" ", " ", $searchword);
    $searchword_array = preg_split("/[ ]+/",$searchword);
    $where = " WHERE 1";
    foreach( $word_array as $row ){
        $where .= " AND concat(id01,' ',id02,' ',id03,' ',id04,' ',id05) LIKE '%{$row}%'";
    }
    $pdo = new PDO('mysql:host=****;dbname=****;','****','****',[ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]);
    $stmt = $pdo->prepare("SELECT * FROM 【table名】 {$where}");
    $stmt->execute();
}
?>
<form action="search.php" method="get">
    <input type="search" name="searchword" value="<?php echo $searchword; ?>">
    <button type="submit"><span>検索</span></button>
</form>
<?php if(!empty($_GET['searchword'])){ ?>
<ul>
<?php
foreach ($stmt as $row) {
    echo '<li> '.$row['value']. '</li>';
}
?>
</ul>
<?php } ?>

注意するところは何点かある。

フォーム部で入力した検索文字列の取得から検索結果出力の発火やらなにやらをするわけだけど、はじめてページを開いたときや空欄で検索した場合は中身が無い。「無」ならいいけど「空が存在する」があるので、両方まとめて発火しない扱いにしたいんで、isset()じゃなくてempty()を採用。

検索ワードは、単語一つだったらいいけど、フリーワード検索だと複数を絡めて入力する場合は普通にある。そうすると検索対象のカラムも複数用意しなければいけない。この部分をきちんと理解していないと終わる。

取得の大枠はこんな感じ。

prepare("SELECT * FROM 【table名】 WHERE 1 AND 【id】 LIKE 【value】 AND 【id】 LIKE 【value】 AND 【id】 LIKE 【value】...")

ANDで繋ぐことで複数の文字列を検索にかけられるようになる。

複数のカラムに対して検索するのはこう。

AND concat(【id01】,' ',【id02】,' ',【id03】,' ',...【id99】) LIKE '%【value】%'

concat()をこんな感じで使う。

検索ワードは部分一致にするのが無難なので、前後に「%」をつけることは必須。その辺りはここを読むとわかりやすい

で、複数の検索ワードに対応するには、例えば「うんこ ちんこ まんこ」を検索したとして、「うんこ ちんこ まんこ」をそのまま検索条件に突っ込むと、この形が含まれた内容を探すことになってしまう。普通の検索ではそういうものは望まれない。「うんこ ちんこ まんこ」が含まれるものじゃなくて、「うんこ」「ちんこ」「まんこ」の3つがどっかに含まれるものを検索したいのが普通。

なので、スペース区切りで入力された検索ワード群をスペース位置で分けて、ワードごとにANDで繋いでいく。そのためのこれ。

    //検索ワード群を変数化
    $searchword = $_GET['searchword'];
    //全角スペースを全て半角スペースに変換
    $searchword = str_replace(" ", " ", $searchword);
    //検索ワード群を半角スペース箇所で区切った配列を作成
    $searchword_array = preg_split("/[ ]+/",$searchword);
    //WHEREの宣言(1は検索条件がない的な意味)
    $where = " WHERE 1";
    //複数条件として検索ワードごとにANDを繋いでいく
    foreach( $searchword_array as $row ){
        $where .= " AND concat(id01,' ',id02,' ',id03,' ',id04,' ',id05) LIKE '%{$row}%'";
    }

そんな感じで。

カラムはconcat()でまとめられたのに検索ワードは無理なんですかね。どうなんでしょうね。

コメント

タイトルとURLをコピーしました