Building a SELECT query as a mysqli prepared statement using a dynamic number of LIKE conditions
P粉269847997
P粉269847997 2024-03-25 23:18:00
0
2
356

I'm trying to write prepared statements for user input. The number of parameters changes based on user input. Oam is trying this code

PHP code:

$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'];
        }
    }
}

When I print_r($inputArray) the output is:

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

No errors are shown in the error log.

What went wrong?

P粉269847997
P粉269847997

reply all(2)
P粉826429907

Write a generic query handler and pass it your query, parameter array, and parameter type list. Returns a set of results or messages. This is my own personal version of mysqli (I mostly use PDO, but have similar functionality set up for this). Do the same for inserts, updates, and deletes. Then just maintain your one library and use it for everything you do :) Note that if you start with this, you may want to handle connection errors etc. better.

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;$iclose();

    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$val){
            print("key:".$key." -> value:".$val);
        }
    }
}

?>
P粉787806024

% Surround parameters, not placeholders.

My code snippet will use object-oriented mysqli syntax, rather than the procedural syntax demonstrated by your code.

First you need to set up the necessary ingredients:

  1. WHERE clause expression -- separated by OR
  2. Data type of the value - your value is a string, so use "s"
  3. Parameters to be bound to prepared statements

I will combine #2 and #3 into a variable for easier "unpacking" using the splat operator (...). The data type string must be the first element, then one or more elements will represent the bound value.

As a logical inclusion, if there is no condition in the WHERE clause, there is no benefit to using a prepared statement; just query the table directly.

Code: (PHPize.online Demo)

$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 "
{$row['name']}
\n"; }

For anyone looking for similar dynamic query techniques:

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template