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";
}