我是一種新的與PDO和當前開發的API調用返回搜索結果。如果搜索查詢有兩個可選參數,如何設置一個準備語句?PDO準備聲明與可選參數
$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 [ '城市']和$ _GET [ '性別']是可選的。如果我嘗試運行上面的代碼,它會假定任何空變量都應該匹配列中的空值;在另一方面,如果我做這樣的事:
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);
}
}
性別是'int'嗎? –
實際上它是一個很小的int(0或1)。但這不是問題。問題是性別和城市(或任何其他未來參數)在查詢字符串中應該是可選的。準備好的聲明是否可行? – andufo
@LuigiSiri我現在使用的PDO :: PARAM_BOOL,因爲它只能是1或0. – andufo