Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用call\u user\u func\u array()动态构建准备好的语句_Php_Mysql_Mysqli - Fatal编程技术网

Php 使用call\u user\u func\u array()动态构建准备好的语句

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

我需要根据用户输入动态构建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 
        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();