topic: db (PDO / SQL / マルチDB) / ch09 — SQL インジェクション / プリペアド vs 連結 / 演習 02
📝 ドリル 02 — LIKE 検索もプレースホルダで
問題
ユーザーが入力したキーワードで users.name を 部分一致検索 (LIKE) するコードを書きたい。
- 標準入力からキーワードを 1 行受け取る
nameにそのキーワードを含むユーザーをid昇順で全件出力する%(ワイルドカード) は PHP 側 で付け、プレースホルダには値だけ渡す
users テーブルには次が入っている (setup.sql 参照):
| id | name |
|---|---|
| 1 | 山田太郎 |
| 2 | 鈴木花子 |
| 3 | 山本次郎 |
| 4 | O'Brien |
期待される入力
山
期待される出力
1: 山田太郎
3: 山本次郎
採点
php scripts/grade.php topics/11-db/ch09-sql-injection/drill/02-search-safe/
ヒント
WHERE name LIKE ?でプレースホルダ- 値の側で
'%' . $keyword . '%'を作って渡す - SQL の中に
'%$keyword%'のように埋め込むのは NG ORDER BY idで並び順を固定
テストケース
標準入力
山
期待される出力
1: 山田太郎
3: 山本次郎
📄 starter.php(雛形)
このコードから書き始めてください。
<?php
$pdo = new PDO('sqlite:' . getenv('DOJO_DB_PATH'));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$keyword = trim(fgets(STDIN));
// TODO: WHERE name LIKE ? でプレースホルダにし、値の側で '%' を付ける
// ORDER BY id で並び順を固定し、 "{id}: {name}" を 1 行ずつ出力する
//
// 期待される出力 (入力が "山" のとき):
// 1: 山田太郎
// 3: 山本次郎
✅ 解答例を見る(自分で解いてから)
<?php
$pdo = new PDO('sqlite:' . getenv('DOJO_DB_PATH'));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$keyword = trim(fgets(STDIN));
$stmt = $pdo->prepare("SELECT id, name FROM users WHERE name LIKE ? ORDER BY id");
$stmt->execute(['%' . $keyword . '%']);
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
echo "{$row['id']}: {$row['name']}\n";
}