PHPとMySQLで検索機能を作成!LIKE検索とPDOの基本を解説【初心者向け】

Webサイトに登録された多くの商品やユーザー情報の中から、目的のデータを素早く見つけ出す「検索機能」は、ユーザーにとって非常に価値の高い機能です。

今回は、PHPとデータベース(MySQL)を連携させ、入力されたキーワードに一致する会員データを一覧表示する、シンプルな検索アプリケーションの作り方を一から解説します。

この解説を通じて、安全なデータベース操作に不可欠なPDOと、あいまい検索を実現するSQLの**LIKE句**という、2つの重要なテクニックをマスターしましょう。


目次

1. 検索フォームのHTMLを作成する

まずは、ユーザーが検索キーワードを入力するためのHTMLフォームを準備します。今回は、1つのPHPファイル(search.phpなど)にフォームと検索結果の両方を表示するため、<form>タグのaction属性は空にします。action=""とすると、フォームのデータは自分自身のページに送信されます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>会員検索アプリ</title>
    </head>
<body>
    <h1>会員検索</h1>
    <p>検索したい会員の名前(一部でも可)を入力してください。</p>
    <form action="" method="POST">
        <label for="name">お名前:</label>
        <input type="text" id="name" name="search_name">
        <input type="submit" value="検索する">
    </form>
</body>
</html>

2. SQLのLIKE句による「あいまい検索」

完全一致のデータを探す場合、SQLではWHERE name = '山田太郎'のように=を使います。しかし、検索機能では「山田」と入力されただけで「山田太郎」さんや「山田花子」さんを見つけ出したいですよね。

このような「部分一致(あいまい検索)」を実現するのがLIKE句と、**ワイルドカード文字%**です。

%は「0文字以上の任意の文字列」を意味します。

パターン意味
'田中%'「田中」で始まる文字列(例: 田中三郎, 田中商店)
'%一郎'「一郎」で終わる文字列(例: 鈴木一郎, 田中一郎)
'%京都%'「京都」を含む文字列(例: 京都府, 東京都京都市)

一般的な検索フォームでは、キーワードがどこに含まれていてもヒットさせたいので、'%キーワード%'の形をよく使います。


3. PHPで安全な検索処理を実装する

それでは、PHPのロジックを組み立てていきます。全体の流れは以下の通りです。

  1. ページがPOST送信されたかどうかを$_SERVER['REQUEST_METHOD']で判定する。
  2. 送信されていたら、検索キーワードを$_POSTから受け取る。
  3. データベースにPDOで接続する。
  4. LIKE句とプリペアドステートメントを使って、安全なSQL文を準備する。
  5. キーワードをSQL文に**バインド(紐付け)**して、実行する。
  6. 取得した結果を配列に格納する。

なぜプリペアドステートメントが必須なのか?

もしユーザーが入力した値を直接SQL文に連結してしまうと、「SQLインジェクション」という非常に危険な攻撃を受ける可能性があります。プリペアドステートメントを使えば、PDOが値を安全な形に処理してくれるため、この攻撃を根本的に防ぐことができます。

LIKE句で値をバインドする際のポイント bindValue()の第2引数で、検索キーワードの前後に%を連結するのがコツです。 $stmt->bindValue(':name', '%' . $search_name . '%', PDO::PARAM_STR);


4. 完成版コード

これまでの要素をすべて統合した、1つのファイルで動作する完成版のコードです。 事前にmembersテーブル(ID, 名前, 年齢, メールアドレスなどを持つ)が用意されていることを前提としています。

search.php

<?php
// ===== 変数の初期化 =====
$search_name = '';
$results = [];
$message = '';

// ===== データベース接続情報 =====
$dsn = 'mysql:dbname=php_learning_db;host=localhost;charset=utf8mb4';
$user = 'root';
$password = ''; // XAMPPのデフォルトは空パスワード

// ===== POSTリクエストがあった場合の検索処理 =====
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $search_name = $_POST['search_name'] ?? '';

    if (!empty($search_name)) {
        try {
            $dbh = new PDO($dsn, $user, $password);
            $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            // SQL文の準備 (LIKE句とプレースホルダを使用)
            $sql = 'SELECT id, name, age FROM members WHERE name LIKE :name';
            $stmt = $dbh->prepare($sql);

            // 値をバインド
            $stmt->bindValue(':name', '%' . $search_name . '%', PDO::PARAM_STR);
            
            // 実行
            $stmt->execute();
            $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

            if (count($results) === 0) {
                $message = '該当する会員が見つかりませんでした。';
            }

        } catch (PDOException $e) {
            $message = "データベースエラー: " . $e->getMessage();
        }
    } else {
        $message = '検索キーワードを入力してください。';
    }
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>会員検索アプリ</title>
    <style>
        body { font-family: sans-serif; }
        .container { width: 80%; margin: 20px auto; }
        table { border-collapse: collapse; width: 100%; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 10px; }
        thead { background-color: #f2f2f2; }
        .message { color: #d9534f; }
    </style>
</head>
<body>
    <div class="container">
        <h1>会員検索</h1>
        <p>検索したい会員の名前(一部でも可)を入力してください。</p>
        <form action="" method="POST">
            <label for="name">お名前:</label>
            <input type="text" id="name" name="search_name" value="<?php echo htmlspecialchars($search_name, ENT_QUOTES, 'UTF-8'); ?>">
            <input type="submit" value="検索する">
        </form>

        <?php if ($_SERVER['REQUEST_METHOD'] === 'POST'): ?>
            <hr>
            <h2>検索結果</h2>
            <?php if (!empty($message)): ?>
                <p class="message"><?php echo $message; ?></p>
            <?php elseif (!empty($results)): ?>
                <table>
                    <thead>
                        <tr>
                            <th>ID</th>
                            <th>名前</th>
                            <th>年齢</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($results as $row): ?>
                            <tr>
                                <td><?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8'); ?></td>
                                <td><?php echo htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8'); ?></td>
                                <td><?php echo htmlspecialchars($row['age'], ENT_QUOTES, 'UTF-8'); ?></td>
                            </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>
            <?php endif; ?>
        <?php endif; ?>
    </div>
</body>
</html>

まとめ

今回は、PHPとMySQLを使った基本的な検索機能の実装方法を学びました。

【重要ポイントの振り返り】

  1. あいまい検索には、SQLの**LIKEとワイルドカード%**を使う。
  2. ユーザーからの入力値を扱う際は、SQLインジェクション対策として必ずPDOのプリペアドステートメントを使用する。
  3. bindValue()で値を紐付ける際に、'%' . $keyword . '%' のように%を連結する。
  4. 1つのファイルにフォームと処理を同居させると、シンプルなアプリを効率的に作れる。

このパターンは、会員検索、商品検索、記事検索など、あらゆるWebアプリケーションの基本となります。ぜひこのコードをベースにして、さまざまな検索機能を実装してみてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次