Developer

【PHP応用】PDO⑯ INを使用したサンプル
2021.09.30
Lv2

【PHP応用】PDO⑯ INを使用したサンプル

PDO⑯ INを使用したサンプル

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

■要件

  • サッカー選手の一覧が表示される
  • チェックを入れて検索すると、選択したポジションの選手が表示される
  • チェックを入れずに検索した場合はヒットしない
  • チェックは検索ボタンを押下後もチェックが状態が維持される

▼ゴールキーパー(GK)とミッドフィルダー(MF)にチェックを入れて検索ボタンを押した場合


▼チェックを入れずに検索ボタンを押した場合


■プログラム

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php
    try {
 
        // 接続処理
        $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.position IN (%s)
        EOM;
 
        // チェックされたポジションを配列で取得。取得できない場合は、空の要素を1つ持つ(SQLの構文エラー対策)
        $positions = isset($_GET['positions']) ? $_GET['positions'] : array('');
 
        // 配列の要素の数だけIN内の?をカンマ区切りで生成し%s部分をprintf関数で置換
        $sql = sprintf($sql, substr(str_repeat(',?', count($positions)), 1));
 
        $stmt = $dbh->prepare($sql);
 
        // ?マークをバインド
        for($i = 0; $i < count($positions); $i++){
            $stmt->bindParam($i + 1, $positions[$i]);
        }
        $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>INを使用したサンプルシステム</title>
    </head>
    <body>
        <div class="container">
 
            <div class="h1 mb-3">INを使用したサンプルシステム</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">
                            <label class="form-check-label" for="">ポジション</label>
                            <div class="col-12">
                                <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="checkbox" name="positions[]" value="GK" id="GK" <?php print(in_array('GK', $positions) ? 'checked' : '' ) ?>>
                                    <label class="form-check-label" for="GK">ゴールキーパー(GK)</label>
                                </div>
                                <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="checkbox" name="positions[]" value="DF" id="DF" <?php print(in_array('DF', $positions) ? 'checked' : '' ) ?>>
                                    <label class="form-check-label" for="DF">ディフェンス(DF)</label>
                                </div>
                                <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="checkbox" name="positions[]" value="MF" id="MF" <?php print(in_array('MF', $positions) ? 'checked' : '' ) ?>>
                                    <label class="form-check-label" for="MF">ミッドフィルダー(MF)</label>
                                </div>
                                <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="checkbox" name="positions[]" value="FW" id="FW" <?php print(in_array('FW', $positions) ? 'checked' : '' ) ?>>
                                    <label class="form-check-label" for="FW">フォワード(FW)</label>
                                </div>
                            </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>

■解説

30行目
チェックなしの場合はarray('');となり、空文字の要素が1つ追加されます。
これがないと、発行されるSQLのINが

1
IN ()

となってSQLの構文エラーとなってしまいます。
空文字を追加することにより、発行されるSQLが

1
IN ('')

となり、エラーにならなくなります。

PHPWEBプログラミング講座 連載目次リンク

PHPWEBプログラミング講座 連載目次