Php 使用call\u user\u func\u array()动态构建准备好的语句
我需要根据用户输入动态构建SQL语句和参数。sql语句的长度和参数的数量会根据用户输入而更改。我正在尝试使用它并将其应用到我的代码中。代码如下:Php 使用call\u user\u func\u array()动态构建准备好的语句,php,mysql,mysqli,Php,Mysql,Mysqli,我需要根据用户输入动态构建SQL语句和参数。sql语句的长度和参数的数量会根据用户输入而更改。我正在尝试使用它并将其应用到我的代码中。代码如下: $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
$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 s.country = ?";
$a_params[] = $place['country'];
$a_param_type[] = "s";
// prepare and bind
$param_type = '';
foreach ($place as $key => $value) {
if ($key === "country") {
continue;
}
$query .= " and s.$key = ?";
$a_params[] = $value;
$a_param_type[] = "s";
}
/* Prepare statement */
$stmt = $conn->prepare($query);
if($stmt === false) {
trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->errno . ' ' . $conn->error, E_USER_ERROR);
}
$a_params[] = $a_param_type;
/* use call_user_func_array, as $stmt->bind_param('s', $param); does not accept params array */
call_user_func_array(array($stmt, 'bind_param'), $a_params);
/* Execute statement */
$stmt->execute();
$meta = $stmt->result_metadata();
我知道,$place['country']
将一直被填充。sql语句是正确的。它是:
"SELECT p.*, s.* \n FROM product p \n INNER JOIN product_shop ps \n ON ps.p_id = p.p_id \n INNER JOIN shop s \n ON s.s_id = ps.s_id \n WHERE s.country = ? and s.suburb = ? and s.city = ? and s.province = ?"
不要介意“\n”字符,它们对sql语句没有影响
在:
$a_params
的值为:
0:"New Zealand"
1:"Grey Lynn"
2:"Auckland"
3:"Auckland"
4:array(4)
0:"s"
1:"s"
2:"s"
3:"s"
在:
$meta的值变为:
current_field:0
field_count:13
lengths:null
num_rows:0
type:1
这意味着没有从数据库中选择任何行。我已经在数据库上手动执行了这个sql,它返回了行。我的代码有什么问题,它没有从数据库返回任何行
编辑:我看到上面说把“SSS”放在$params
的开头,所以我这样做了,并在$stmt
对象中得到了这个错误:
errno:2031
error:"No data supplied for parameters in prepared statement"
error_list:array(1)
propertyNode.hasAttribute is not a function
我不明白你用了什么方法,但我会尽力回答: 根据:
bind_param
的第一个参数是一个字符串,类似于'ssss'
第二个参数和其他参数-是要插入到查询中的值
因此,您的$a_参数
数组应该是而不是
0:"New Zealand"
1:"Grey Lynn"
2:"Auckland"
3:"Auckland"
4:array(4)
0:"s"
1:"s"
2:"s"
3:"s"
但是:
看到了吗?所有值都是字符串。占位符的类型是第一个
还要考虑到,$a_参数
中的参数顺序必须与bind_参数
中的参数顺序相同。这意味着,即,$a_参数
类似
0:"New Zealand"
1:"Grey Lynn"
2:"Auckland"
3:"Auckland"
4:"ssss"
这是错误的。因为$a_params
的第一个元素将是bind_param
的第一个参数,在这种情况下,它不是“ssss”
字符串
因此,这意味着在用值填充$a_参数
后,占位符字符串应添加到$a_参数
的开头,例如数组_unshift
:
// make $a_param_type a string
$str_param_type = implode('', $a_param_type);
// add this string as a first element of array
array_unshift($a_params, $str_param_type);
// try to call
call_user_func_array(array($stmt, 'bind_param'), $a_params);
如果这不起作用,您可以引用的一部分,其中$a_params
的值通过引用传递到另一个数组$tmp
,在您的情况下,您可以尝试以下操作:
// make $a_param_type a string
$str_param_type = implode('', $a_param_type);
// add this string as a first element of array
array_unshift($a_params, $str_param_type);
$tmp = array();
foreach ($a_params as $key => $value) {
// each value of tmp is a reference to `$a_params` values
$tmp[$key] = &$a_params[$key];
}
// try to call, note - with $tmp, not with $a_params
call_user_func_array(array($stmt, 'bind_param'), $tmp);
请记住:
call\u user\u func\u array
的第二个参数需要引用,而不仅仅是普通数组。这是关键。被接受的答案是好的,但缺少一点,即引用参数:
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();
您的
call\u user\u func\u array()
参数不应该有点不同吗?更像是类型字符串、value1、value2
等等。@RST我这样尝试过:0:“新西兰”1:“灰色Lynn”2:“奥克兰”3:“奥克兰”4:“ssss”
还有:0:“ssss”1:“新西兰”2:“灰色Lynn”3:“奥克兰”4:“奥克兰”
但它没有返回任何行。如果使用$stmt->bind\u param('s',$param);
和内爆()
使用前请先使用数组them@RST你能给我一个这样的代码示例吗?我想确保我试得正确。ssss
是字符串还是数组?
// make $a_param_type a string
$str_param_type = implode('', $a_param_type);
// add this string as a first element of array
array_unshift($a_params, $str_param_type);
// try to call
call_user_func_array(array($stmt, 'bind_param'), $a_params);
// make $a_param_type a string
$str_param_type = implode('', $a_param_type);
// add this string as a first element of array
array_unshift($a_params, $str_param_type);
$tmp = array();
foreach ($a_params as $key => $value) {
// each value of tmp is a reference to `$a_params` values
$tmp[$key] = &$a_params[$key];
}
// try to call, note - with $tmp, not with $a_params
call_user_func_array(array($stmt, 'bind_param'), $tmp);
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();