私は PDO の初心者で、現在、検索結果を返す API 呼び出しを開発しています。検索クエリに 2 つのオプション パラメータがある場合、prepare ステートメントを設定するにはどうすればよいですか?
$app->get('/get/search', function () {
$sql = 'SELECT * FROM user WHERE name LIKE :name AND city = :city AND gender = :gender';
try {
$stmt = cnn()->prepare($sql);
$stmt->bindParam(':name', '%'.$_GET['name'].'%', PDO::PARAM_STR);
$stmt->bindParam(':city', '%'.$_GET['city'].'%', PDO::PARAM_STR);
$stmt->bindParam(':gender', $_GET['gender'], PDO::PARAM_INT);
$stmt->execute();
if($data = $stmt->fetchAll()) {
echo json_encode($data);
} else {
echo json_encode(array('error' => 'no records found');
}
} catch(PDOException $e) {
echo json_encode(array('error' => $e->getMessage()));
}
}
ここでの問題は、$_GET['city']と$_GET['gender'] の両方がオプションであることです。上記のコードを実行しようとすると、空の変数は列の空の値にも一致する必要があると想定されます。一方、次のようなことをすると:
if($_GET['gender']) $stmt->bindParam(':gender', $_GET['gender'], PDO::PARAM_INT);
...次のエラーが返されます: "SQLSTATE[HY093]: 無効なパラメーター番号: バインドされた変数の数がトークンの数と一致しません"
では、オプションのパラメーターに対して準備済みの sql ステートメントを保持したい場合の解決策は何ですか? ありがとう!
アップデート
これは、受け入れられた回答といくつかのコメント ( decezeおよびbill-karwin による)に基づくソリューションです。
if($_GET['name']) $where[] = 'name LIKE :name';
if($_GET['city']) $where[] = 'city LIKE :city';
if(isset($_GET['gender'])) $where[] = 'gender = :gender';
if(count($where)) {
$sql = 'SELECT * FROM user WHERE '.implode(' AND ',$where);
$stmt = cnn()->prepare($sql);
$name = '%'.$_GET['name'].'%';
if($_GET['name']) $stmt->bindValue(':name', '%'.$_GET['name'].'%', PDO::PARAM_STR);
$city = '%'.$_GET['city'].'%';
if($_GET['city']) $stmt->bindParam(':city', $city, PDO::PARAM_STR);
if(isset($_GET['gender'])) $stmt->bindParam(':gender', $_GET['gender'], PDO::PARAM_BOOL);
$stmt->execute();
if($data = $stmt->fetchAll()) {
echo json_encode($data);
}
}