2014-04-14 18 views
0

我目前在一個網站中,用戶能夠從數據庫中搜索使用許多不同的標準(以事件從一個創建一個非常簡單的搜索功能的過程許多不同的數字),而且我正在使用準備好的語句,特別是bind_param()時遇到了問題。簡單的搜索功能中,MySQL準備好的語句問題

下面是相關PHP代碼:

... 
... 
$title = (empty($_POST['eventTitle'])) ? null : $_POST['eventTitle']; 
$venue = (empty($_POST['venue'])) ? null : $_POST['venue']; 
$catID = (empty($_POST['catID'])) ? null : $_POST['catID']; 
$start = (empty($_POST['start'])) ? null : $_POST['start']; 
$end = (empty($_POST['end'])) ? null : $_POST['end']; 
$price = (empty($_POST['price'])) ? null : $_POST['price']; 

include 'database_conn.php'; 

$sql = 'SELECT eventID, eventTitle, venueID, catID, eventStartDate, 
eventEndDate, eventPrice FROM te_events WHERE 1'; 

$sqlCondition = ''; 

$bindFirstArg = '"'; 
$bindSecondArg = ''; 

if($title !== null && !empty($title)) { 

    $sqlCondition = $sqlCondition . " AND eventTitle LIKE \"%" 
    . $title . "%\""; 

} 

if($venue !== null && $venue !== '0') { 

    $sqlCondition = $sqlCondition . " AND venueID=?"; 
    $bindFirstArg = $bindFirstArg . "s"; 
    $bindSecondArg = $bindSecondArg . ", " . $venue; 

} 

if($catID !== null && $catID !== '0') { 

    $sqlCondition = $sqlCondition . " AND catID=?"; 
    $bindFirstArg = $bindFirstArg . "s"; 
    $bindSecondArg = $bindSecondArg . ", " . $catID; 

} 

if($start !== null && $start !== '0') { 

    $sqlCondition = $sqlCondition . " AND eventStartDate=?"; 
    $bindFirstArg = $bindFirstArg . "s"; 
    $bindSecondArg = $bindSecondArg . ", " . $start; 

} 

if($end !== null && $end !== '0') { 

    $sqlCondition = $sqlCondition . " AND eventEndDate=?"; 
    $bindFirstArg = $bindFirstArg . "s"; 
    $bindSecondArg = $bindSecondArg . ", " . $end; 

} 

if($price !== null && !empty($price)) { 

    $sqlCondition = $sqlCondition . " AND eventPrice=?"; 
    $bindFirstArg = $bindFirstArg . "i"; 
    $bindSecondArg = $bindSecondArg . ", " . $price; 

} 

$sql = $sql . $sqlCondition; 
$bindFirstArg = $bindFirstArg . '"'; 

$search_stmt = $conn -> prepare($sql); 

if (false===$search_stmt) { 

    die('prepare() failed: ' . htmlspecialchars($conn->error)); 

} 


$search_stmt -> bind_param($bindFirstArg, $bindSecondArg); 
$search_stmt -> execute(); 
$search_stmt -> bind_result($eventIDRes, $eventTitleRes, $venueIDRes, 
$catIDRes, $eventStartRes, $eventEndRes, $eventPriceRes); 

while ($search_stmt->fetch()) { 

    printf ("%s %s %s %s %s %s %i\n", $eventIDRes, $eventTitleRes, 
    $venueIDRes, $catIDRes, $eventStartRes, $eventEndRes, $eventPriceRes); 

} 

mysqli_stmt_close($search_stmt); 

錯誤我收到美國

警告:mysqli_stmt :: bind_param()[mysqli的-stmt.bind-PARAM]:數字類型定義字符串中元素的數量不匹配/var/www/vhosts/numyspace.co.uk/web_users/home/~unn_w12019212/public_html/webdev/ searchresult.php on line 101中綁定變量的數量「

任何想法?

+0

您需要爲您的查詢中的每個*'?'傳遞'bind_param'參數。你只傳遞一個參數('$ bindSecondArg')。 –

+3

MySQLi預準備語句要求您爲每個參數指定一個數據類型。 –

+0

@RocketHazmat - $ bindSecondArg是用來裝它是根據用戶的選擇範圍內的,所以在現實中,它在其內具有多個變量的變量名的變量。 – Charlieabee

回答

1

你需要傳遞一個bind_param單獨參數在您的查詢中的每個?,以及格式作爲第一個參數。你不能傳遞一個逗號分隔的字符串,這是行不通的。它只是讀作爲第一個?,然後抱怨說你沒有發送剩下的東西。

另外,不要你$bindFirstArg字符串中添加引號。 bind_param只是希望所有的數據類型(ids,或b),它不希望"字符的列表。

你需要做的是把你的值到一個數組,然後通過call_user_func_array調用bind_param

$sqlCondition = ''; 

$bindFirstArg = ''; 
$bindParams = array(); 


// You need to bind $title as well, otherwise you are wide open to SQL 
// injection and have just thrown out the benefits of prepared statements 
if($title !== null && !empty($title)) { 
    $sqlCondition .= " AND eventTitle LIKE ?"; 
    $bindFirstArg .= "s"; 

    // Add the `%` to the value, not the query 
    $title = "%{$title}%"; 
    // bind_param wants these to be references 
    $bindParams[] =& $title; 

} 

// Change all your ifs to look like this. 
// They need to push into the $bindParams array 
if($catID !== null && $catID !== '0') { 
    $sqlCondition .= " AND catID=?";  
    $bindFirstArg .= "s"; 

    // bind_param wants these to be references 
    $bindParams[] =& $catID; 
} 

// etc... 

$sql .= $sqlCondition; 
$search_stmt = $conn->prepare($sql); 

// Call bind_param with the correct number of parameters 
array_unshift($bindParams, $bindFirstArg); 
// This will make sure the parameters are passed correctly. 
// Each variable needs to be passed as a separate parameter 
call_user_func_array(array($search_stmt, 'bind_param'), $bindParams); 

$search_stmt->execute(); 
$search_stmt->bind_result($eventIDRes, $eventTitleRes, $venueIDRes, 
    $catIDRes, $eventStartRes, $eventEndRes, $eventPriceRes); 

while ($search_stmt->fetch()) { 
    printf ("%s %s %s %s %s %s %i\n", $eventIDRes, $eventTitleRes, 
     $venueIDRes, $catIDRes, $eventStartRes, $eventEndRes, $eventPriceRes); 
} 

$search_stmt->close(); 
+0

是的,這是可行的,謝謝。不過,我不確定它爲什麼會起作用,所以我不得不自己去研究一下! – Charlieabee

+0

魔術是'call_user_func_array'函數:-) –