我正在尝试使用动态where子句和动态参数创建一个选择查询,但是我总是遇到错误:
警告:mysqli_stmt :: bind_param():类型中的元素数 定义字符串与绑定变量的数量不匹配
我真诚地不理解,因为似乎计数还可以。因此,这就是代码的粗鲁形式。我看不到我在做什么错。
//get variables
$mediaArray ='Facebook,Twitter,Twitch,';
$otherMedia = 'House';
//convert string to array
$socialArray = explode(',', $mediaArray)
//declare some variables to be used later
$andwhere = '';
$bp = '';
$socialmarray = ''
//get every value from array of social media
foreach($socialArray as $socialmedia){
$socialmarray .=$socialmedia.',';
$andwhere .= " AND socialmedianame=?";
$bp .='s';
}
//test strings
echo $wheres = $andwhere;//AND socialmedianame=? AND socialmedianame=? AND socialmedianame=?
echo $bip = $bp.'s';//ssss
echo $validarayy = rtrim($socialmarray,',');//Facebook,Twitter,Twitch
//select query
$selectquery = $conn->prepare("select * from mediaservices where socialmedianame=? $wheres");
$selectquery->bind_param("$bip",$otherMedia,$validarayy);
$selectquery->execute();
$resultquery = $selectquery->get_result();
答案 0 :(得分:2)
在您的查询中:
$selectquery = $conn->prepare("select * from mediaservices where socialmedianame=? $wheres");
?
代表一个要传入的参数,而$wheres
的求值又添加了三个,从而为您提供了四个参数。
bind_param()
应该将表示要插入的变量类型的字符串作为第一个参数,并将变量本身作为后续参数。
在您的绑定中:
$selectquery->bind_param("$bip",$otherMedia,$validarayy);
$bip
的值为ssss
,并且$otherMedia
是单个字符串("House"
)。您可能希望$validarayy
是三个字符串,但是 rtrim()
返回一个字符串。因此,它只是一个字符串("Facebook,Twitter,Twitch"
)。当查询需要四个变量时,您将传递两个变量:
$conn->prepare("select * from mediaservices where socialmedianame=House AND socialmedianame=Facebook,Twitter,Twitch AND socialmedianame=? AND socialmedianame=? AND socialmedianame=?"
要解决此问题,您需要将$validarayy
转换回数组,并将索引用于各种输入:
$socialmarray2 = explode(',', $validarayy);
$selectquery->bind_param("$bip", $otherMedia, $socialmarray2[0], $socialmarray2[1], $socialmarray2[2]);
还请注意,您的示例代码缺少一些分号。您需要修复这些问题才能使代码正常工作。
可以在 here 上看到它。
最后,请注意,即使您正确地分割了三个字符串,选择... AND socialmedianame=Facebook AND socialmedianame=Twitter AND socialmedianame=Twitch
也不会匹配任何结果; socialmedianame
只能包含一个值。您可能正在寻找将AND
语句替换为OR
语句。
答案 1 :(得分:2)
因为:
您应该使用准备好的语句,并将所有WHERE
子句逻辑合并到单个IN
语句中。
(在语法上)构建动态准备语句比使用pdo更为复杂,但这并不意味着您仅由于此任务就需要放弃mysqli。
我已经遍历所有可能的错误检查点,以便您可以轻松调试是否出现意外情况。我必须强调,作为最佳安全实践,您绝不能向公众展示错误详细信息。
我已经在本地主机上使用自己的db数据测试了该解决方案,这是一个可行的解决方案。
$_POST['userMedia'] ='Facebook,Twitter,Twitch,';
$media = explode(',', rtrim($_POST['userMedia'], ',')); // build array from csv string
$presetMedia = 'House';
$media[] = $presetMedia; // push known media string into array
$media = array_unique($media); // make sure there are no duplicates
var_export($media); // see what this generates
if (!$count = count($media)) {
echo "There are no values in media, so a prepared statement is overkill and IN won't work when empty";
// handle this case however you wish (if it is even possible within your project)
} elseif (!$conn = new mysqli("localhost", "root", "", "myDB")) { // use your own credentials
echo "Database Connection Error: " , $conn->connect_error;
} else {
$csph = implode(',', array_fill(0, $count, '?')); // comma-separated placeholders e.g: ?,?,?,?
echo "<div>Placeholders: $csph</div>";
$query = "SELECT * FROM `mediaservices` WHERE `socialmedianame` IN ($csph)";
echo "<div>Query: $query</div>";
if (!$stmt = $conn->prepare($query)) {
echo "<div>Syntax Error @ prepare: {$conn->error}</div>"; // NEVER show error details to the public
}else{
array_unshift($media, str_repeat('s', $count)); // prepend the type values string e.g: ssss
var_export($media); // see what this generates
foreach ($media as &$v) {
$ref[] = &$v; // call_user_func_array requires array that is passed-by-reference
}
call_user_func_array([$stmt, 'bind_param'], $ref); // call bind_param() upon stmt object, using each media value
if (!$stmt->execute() || !$result = $stmt->get_result()) { // execute statement and get the resultset while checking for falsey returned feedback
echo "<div>Error @ execute/get_result: {$stmt->error}</div>"; // NEVER show error details to the public
} elseif (!$result->num_rows) { // check for empty rows, if you wish
echo "<div>No Rows Found</div>";
} else {
echo "<pre>";
while ($row = $result->fetch_assoc()) {
var_export($row); // do what you like with the associative-keyed elements
echo "<br>";
}
echo "</pre>";
}
$stmt->close();
}
}
输出应类似于:
array ( 0 => 'Facebook', 1 => 'Twitter', 2 => 'Twitch', 3 => 'House' )
Placeholders: ?,?,?,?
Query: SELECT * FROM `mediaservices` WHERE `socialmedianame` IN (?,?,?,?);
array ( 0 => 'ssss', 1 => 'Facebook', 2 => 'Twitter', 3 => 'Twitch', 4 => 'House', )
array (
// whatever column names and values you have in the row
)
array (
// whatever column names and values you have in the row
)
array (
// whatever column names and values you have in the row
)
...