使用动态数量的 LIKE 条件构建 SELECT 查询作为 mysqli 预准备语句

Build SELECT query with dynamic number of LIKE conditions as a mysqli prepared statement

提问人:Vinay 提问时间:6/24/2018 最后编辑:mickmackusaVinay 更新时间:8/25/2023 访问量:2342

问:

我正在尝试为用户输入编写准备好的语句。参数编号是可变的,具体取决于用户输入。Oam 尝试此代码

PHP代码:

$string          = "my name";
$search_exploded = explode( " ", $string );
$num             = count( $search_exploded );
$cart            = array();
for ( $i = 1; $i <= $num; $i ++ ) {
    $cart[] = 's';
}
$str          = implode( '', $cart );
$inputArray[] = &$str;
$j            = count( $search_exploded );
for ( $i = 0; $i < $j; $i ++ ) {
    $inputArray[] = &$search_exploded[ $i ];
}
print_r( $inputArray );
foreach ( $search_exploded as $search_each ) {
    $x ++;
    if ( $x == 1 ) {
        $construct .= "name LIKE %?%";
    } else {
        $construct .= " or name LIKE %?%";
    }
}
$query = "SELECT * FROM info WHERE $construct";
$stmt  = mysqli_prepare( $conn, $query );
call_user_func_array( array( $stmt, 'bind_param' ), $inputArray );
if ( mysqli_stmt_execute( $stmt ) ) {

    $result = mysqli_stmt_get_result( $stmt );
    if ( mysqli_num_rows( $result ) > 0 ) {
        echo $foundnum = mysqli_num_rows( $result );
        while( $row = mysqli_fetch_array( $result, MYSQLI_ASSOC ) ) {

            echo $id = $row['id'];
            echo $name = $row['name'];
        }
    }
}
    

当 I 时,输出为:print_r($inputArray)

Array ( [0] => ss [1] => my [2] => name ) 

错误日志中未显示任何错误。

怎么了?

php select mysqli 预备语句 sql-like

评论

0赞 Nigel Ren 6/24/2018
你在$query得到了什么?
0赞 Mr Glass 6/24/2018
你正在爆炸你的 “ ”,所以你会期望你给你两个条目:和 .$stringforeach()myname
0赞 Vinay 6/24/2018
这是查询: SELECT * FROM info WHERE name LIKE %?% or name LIKE %?%
0赞 Vinay 6/24/2018
是的,我想在名称列中搜索“我的”和“名称”。
0赞 Nigel Ren 6/24/2018
将 LIKE 与绑定变量一起使用时,必须在绑定变量中包含 % 符号,而不是 SQL。

答:

-1赞 ivanivan 6/25/2018 #1

编写一个泛型查询处理程序,并向其传递您的查询、参数数组和参数类型列表。取回一系列结果或消息。这是我自己的mysqli个人版本(我主要使用PDO,但也为此设置了类似的函数)。对插入、更新和删除执行相同的操作。然后只需维护您的一个库并将其用于您所做的一切:)请注意,如果您从此开始,您可能希望在处理连接错误等方面做得更好。

<?php

// this is normally in an include() file
function getDBConnection(){

    // your DB credentials

    $hostname="127.0.0.1";
    $username="ausername";
    $password="supersecret";
    $database="some_db_name";

    $con = new mysqli($hostname, $username,$password, $database);
    if($con->connect_error) {
      return false;
    }
    return $con;
}

// generic select function.
// takes a query string, an array of parameters, and a string of
// parameter types
// returns an array - 
//   if $retVal[0] is true, query was successful and returned data
//   and $revVal[1...N] contain the results as an associative array
//   if $retVal[0] is false, then $retVal[1] either contains the 
//   message "no records returned" OR it contains a mysql error message

function selectFromDB($query,$params,$paramtypes){

    // intitial return;
    $retVal[0]=false;

    // establish connection
    $con = getDBConnection();
    if(!$con){
        die("db connection error");
        exit;
    }

    // sets up a prepared statement
    $stmnt=$con->prepare($query);
    $stmnt->bind_param($paramtypes, ...$params);
    $stmnt->execute();

    // get our results
    $result=$stmnt->get_result()->fetch_all(MYSQLI_ASSOC);
    if(!$result){
    $retVal[1]="No records returned";
    }else{
        $retVal[0]=true;
        for($i=0;$i<count($result);$i++){
            $retVal[]=$result[$i];
        }
    }

    // close the connection
    $con->close();

    return $retVal;

}

$myusername=$_POST['username'];
$mypassword=$_POST['password'];

// our query, using ? as positional placeholders for our parameters
$q="SELECT useridnum,username FROM users WHERE username=? and password=?";

// our parameters as an array - 
$p=array($myusername,$mypassword);

// what data types are our params? both strings in this case
$ps="ss";

// run query and get results
$result=selectFromDB($q,$p,$ps);

// no matching record OR a query error
if(!$result[0]){
    if($result[1]=="no records returned"){
        // no records
        // do stuff
    }else{
        // query error
        die($result[1]);
        exit;
    }   
}else{  // we  have matches!
    for($i=1;$i<count($result);$i++){
        foreach($result[$i] as $key->$val){
            print("key:".$key." -> value:".$val);
        }
    }
}

?>

评论

0赞 mickmackusa 6/3/2020
此代码段不支持可变数量的绑定变量。
11赞 mickmackusa 6/26/2018 #2

换行围绕参数,而不是占位符。%

我的代码片段将使用面向对象的 mysqli 语法,而不是您的代码演示的过程语法。

首先,您需要设置必要的成分:

  1. WHERE 子句表达式 -- 用 OR 分隔
  2. 值的数据类型 -- 值是字符串,因此请使用“s”
  3. 要绑定到预准备语句的参数

我将把 #2 和 #3 合并为一个变量,以便使用 splat 运算符 () 更简单地“解包”。数据类型字符串必须是第一个元素,然后一个或多个元素将表示绑定值。...

作为逻辑包含,如果 WHERE 子句中没有条件,则使用准备好的语句没有任何好处;直接查询表即可。

代码:(PHPize.online 演示)

$string = "Bill N_d Dave";

$conditions = [];
$parameters = [''];
foreach (array_unique(explode(' ', $string)) as $value) {
    $conditions[] = "name LIKE ?";
    $parameters[0] .= 's';
    // $value = addcslashes($value, '%_'); // if you want to make wildcards from input string literal. https://stackoverflow.com/questions/18527659/how-can-i-with-mysqli-make-a-query-with-like-and-get-all-results#comment132930420_36593020
    $parameters[] = "%{$value}%";
}
// $parameters now holds ['sss', '%Bill%', '%N_d%', '%Dave%']

$query = "SELECT * FROM info";
if ($conditions) {
    $stmt = $mysqli->prepare($query . ' WHERE ' . implode(' OR ', $conditions));
    $stmt->bind_param(...$parameters);
    $stmt->execute();
    $result = $stmt->get_result();
} else {
    $result = $conn->query($query);
}
foreach ($result as $row) {
    echo "<div>{$row['name']}</div>\n"; 
}

对于任何寻找类似动态查询技术的人: