我必须建立一个sql语句和来自$ place对象的params,它具有可变数量的属性。当我通过构建sql语句来使用准备好的sql语句时,并使用它操作的长而不好的实践方式(返回数据库中应该的所有行):
<?
function buildSQLWhereClause($query, $conn, $place) {
if ($place['suburb']){
if($place['city'] && $place['province'] && $place['country']) {
$query .= "s.country = ? and
s.province = ? and
s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ssss", $place['country'], $place['province'], $place['city'], $place['suburb']);
} else if ($place['province'] && $place['country']) {
$query .= "s.country = ? and
s.province = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['country'], $place['province'], $place['suburb']);
} else if ($place['city'] && $place['province']) {
$query .= "s.province = ? and
s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['province'], $place['city'], $place['suburb']);
} else if ($place['city'] && $place['country']) {
$query .= "s.country = ? and
s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['country'], $place['city'], $place['suburb']);
} else if ($place['city']) {
$query .= "s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['city'], $place['suburb']);
} else if ($place['province']) {
$query .= "s.province = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['province'], $place['suburb']);
} else if ($place['country']) {
$query .= "s.country = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['country'], $place['suburb']);
} else {
$query .= "s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['suburb']);
}
//////////////////////////// NO SUBURB ///////////////////////////////////////////////////
} else if ($place['city']) {
if ($place['province'] && $place['country']) {
$query .= "s.country = ? and
s.province = ? and
s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['country'], $place['province'], $place['city']);
} else if ($place['province']) {
$query .= "s.province = ? and
s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['province'], $place['city']);
} else if ($place['country']) {
$query .= "s.country = ? and
s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['country'], $place['city']);
} else {
$query .= "s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['city']);
}
//////////////////////// NO SUBURB OR CITY ////////////////////////////////////////////////////////
} else if ($place['province']) {
if ($place['country']) {
$query .= "s.country = ? and
s.province = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['country'], $place['province']);
} else {
$query .= "s.province = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['province']);
}
//////////////////////////////// NO SUBURB, CITY, OR PROVINCE ///////////////////////////////
} else if ($place['country']) {
$query .= "s.country = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['country']);
}
return $stmt;
}
function queryDbForProducts($conn, $place)
{
$query = "SELECT p.*, s.*
FROM product p
INNER JOIN product_shop ps
ON ps.p_id = p.p_id
INNER JOIN shop s
ON s.s_id = ps.s_id
WHERE ";
$stmt = buildSQLWhereClause($query, $conn, $place);
$stmt->execute();
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] =& $row[$field->name];
}
当我通过构建sql语句使用sql准备语句并以更好的方式编写索引时,它不起作用:
<?
function buildSQLWhereClause($place) {
$query = "SELECT p.*, s.* FROM product p INNER JOIN product_shop ps ON ps.p_id = p.p_id INNER JOIN shop s ON s.s_id = ps.s_id WHERE ";
$queryParams = [];
$queryParamTypes = "";
$i = 0;
$len = count($place);
foreach ($place as $key => $value) {
if ($i == $len - 1) {
$query .= "$key = ?";
$queryParams[] = $value;
$queryParamTypes .= "s";
} else {
$query .= "$key = ? AND ";
$queryParams[] = $value;
$queryParamTypes .= "s";
}
$i++;
}
return array(
"query" => $query,
"queryParams" => $queryParams,
"queryParamTypes" => $queryParamTypes
);
}
function queryDbForProducts($conn, $place)
{
$queryObject = buildSQLWhereClause($place);
$query = $queryObject['query'];
$queryParams = $queryObject['queryParams'];
$queryParamTypes = $queryObject['queryParamTypes'];
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param($queryParamTypes, $queryParams);
$stmt->execute();
$meta = $stmt->result_metadata();
将鼠标悬停在调试器中的$ stmt上显示:
affected_rows:-1
insert_id:0
num_rows:0
param_count:4
field_count:13
errno:2031
error:"No data supplied for parameters in prepared statement"
error_list:array(1)
sqlstate:"HY000"
id:1
没有提供数据?将鼠标悬停在调试器中的$ queryParams参数上会显示:
0:"Grey Lynn"
1:"Auckland"
2:"Auckland"
3:"New Zealand"
所以我确实向$stmt->bind_param()
函数提供了查询参数。我是以错误的格式提供的吗?
将鼠标悬停在$ QueryParamTypes上会显示:
"ssss"
将鼠标悬停在$ query上显示:
"SELECT p.*, s.* FROM product p INNER JOIN product_shop ps ON ps.p_id = p.p_id INNER JOIN shop s ON s.s_id = ps.s_id WHERE suburb = ? AND city = ? AND province = ? AND country = ?"
当完成问题顶部的代码时它是如何工作的,并且在没有所有is语句的情况下完成代码时它不起作用?
答案 0 :(得分:2)
bind_param
不会将数组作为参数,它需要varargs。如果要使用动态数量的参数调用它,则需要使用call_user_func_array
。
即
$params = array_unshift($queryParams, $queryParamTypes);
call_user_func_array(array($stmt, "bind_param"), $params);
答案 1 :(得分:0)
需要引用传递给call_user_func_array参数2的参数。
这是可行的解决方案:
function makeValuesReferenced($arr){
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
$stmt = $conn->prepare($query);
//$stmt->bind_param($queryParamTypes, $queryParams);
call_user_func_array(array($stmt, 'bind_param'), makeValuesReferenced($queryParams));
$stmt->execute();
不知道引用的东西长时间困扰我。希望这可以帮助一些人。