Developer

【PHP応用】PDO⑭ LIKEを使用したサンプル
2021.09.30
Lv1

【PHP応用】PDO⑭ LIKEを使用したサンプル

PDO⑭ LIKEを使用したサンプル

LIEKを使用したサンプルシステムをご紹介します。
データは別の記事で使用しているものを使用します。
以下リンクの下部にある「動作環境について」の項目から環境を作成してください。
SQL練習問題 – 一覧まとめ

■要件

  • サッカー選手の一覧が表示される
  • 検索欄に名前を入力し検索すると、選手名の部分一致で検索ができる
  • 検索ボタンを押下後も入力した名前が入力欄に維持される



■プログラム

※デザインにBootstrap5を使用しています。
pdo_like.php

<?php
    try {

        // 入力された検索したい名前を取得
        $playerName = isset($_GET['playerName']) ? $_GET['playerName'] : '';

        // 接続処理
        $dsn = 'mysql:host=localhost;dbname=worldcup2014';
        $user = 'root';
        $password = '';
        $dbh = new PDO($dsn, $user, $password);

        // SELECT文を発行
        $sql = <<<EOM
            SELECT
                p.id AS playerId
                , p.name AS playerName
                , c.name AS countryName
                , p.club
                , p.position
                , p.uniform_num AS uniformNum
                , p.birth
                , p.height
                , p.weight 
            FROM
                players p JOIN countries c 
                    ON p.country_id = c.id
            WHERE
                p.name LIKE :playerName
        EOM;

        $stmt = $dbh->prepare($sql);
        $bindPlayerName = '%'.$playerName.'%'; // 検索したい名前の前後に%を付与
        $stmt->bindParam(':playerName', $bindPlayerName, PDO::PARAM_STR);
        $stmt->execute();
        $rows = $stmt->fetchAll(PDO::FETCH_OBJ); // レコードを取得

        // 接続切断
        $dbh = null;

    } catch (PDOException $e) {
        print $e->getMessage() . "<br/>";
        die();
    }
?>

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
        <title>LIKEを使用したサンプルシステム</title>
    </head>
    <body>
        <div class="container">

            <div class="h1 mb-3">LIKEを使用したサンプルシステム</div>


            <div class="card mb-3">
                <div class="card-header bg-primary text-white">
                    検索
                </div>
                <div class="card-body">
                    <form action="">
                        <div class="row mb-3">
                            <div class="col-6">
                                <label for="playerName" class="form-label">選手の名前</label>
                                <input type="playerName" class="form-control" id="playerName" name="playerName" placeholder="" value="<?php print($playerName); ?>">
                            </div>
                        </div>
                    
	                    <button type="submit" class="btn btn-primary">検 索</button>
                    </form>
                </div>
            </div>



            <table class="table table-striped">
                <tr>
                    <th>ID</th>
                    <th>名前</th>
                    <th>国名</th>
                    <th>所属クラブ</th>
                    <th>ポジション</th>
                    <th>背番号</th>
                    <th>生年月日</th>
                    <th>身長</th>
                    <th>体重</th>
                </tr>

        <?php
            if($rows) {
                foreach($rows as $row){
        ?>
                <tr>
                    <td><?php print($row->playerId) ?></td>
                    <td><?php print($row->playerName) ?></td>
                    <td><?php print($row->countryName) ?></td>
                    <td><?php print($row->club) ?></td>
                    <td><?php print($row->position) ?></td>
                    <td><?php print($row->uniformNum) ?></td>
                    <td><?php print($row->birth) ?></td>
                    <td><?php print($row->height) ?>cm</td>
                    <td><?php print($row->weight) ?>kg</td>
                </tr>
        <?php
                }
            }
        ?>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
    </body>
</html>

■解説

ポイントは33行目。
入力された値の前後に%を文字列結合しています。
これにより

WHERE p.name LIKE '%入力値%'

とバインドされます。
バインドする際、前後に自動でシングルクォートが付与されるため、入力値に%を結合しなければいけません。

間違い例

// 中略
WHERE
p.name LIKE %:playerName%
EOM;
// 中略
$stmt->bindParam(':playerName', $bindPlayerName, PDO::PARAM_STR);
// 中略

この場合、発行されるSQLは

WHERE p.name LIKE %'入力値'%

となり、構文エラーとなってしまいます。