使用动态数量的 LIKE 条件构建 SELECT 查询作为 mysqli 准备语句
Build SELECT query with dynamic number of LIKE conditions as a mysqli prepared statement
我正在尝试为用户输入编写准备好的语句。参数编号是可变的,取决于用户输入。 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'];
}
}
}
当我print_r($inputArray)
时,输出为:
Array ( [0] => ss [1] => my [2] => name )
错误日志中没有显示错误。
怎么了?
编写通用查询处理程序并将您的查询、参数数组和参数类型列表传递给它。取回一组结果或消息。这是我自己的 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);
}
}
}
?>
%
环绕参数,而不是占位符。
我的代码片段将使用面向对象的 mysqli 语法,而不是您的代码演示的过程语法。
首先你需要设置必要的成分:
- WHERE 子句表达式 -- 由 OR 分隔
- 您的值的数据类型 -- 您的值是字符串,因此请使用“s”
- 准备语句绑定的参数
我打算将#2 和#3 组合成一个变量,以便使用 splat 运算符 (...
) 更简单地“解包”。数据类型字符串必须是第一个元素,然后一个或多个元素将表示绑定值。
作为逻辑包含,如果您的 WHERE 子句中没有条件,则使用准备好的语句没有任何好处;直接查询 table.
代码:(100% 测试/成功代码)
$string = "my name";
$conditions = [];
$parameters = [''];
foreach (array_unique(explode(' ', $string)) as $value) {
$conditions[] = "name LIKE ?";
$parameters[0] .= 's';
$parameters[] = "%{$value}%";
}
// $parameters now holds ['ss', '%my%', '%name%']
$query = "SELECT * FROM info";
if ($conditions) {
$stmt = $conn->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']} and whatever other columns you want</div>";
}
对于寻找类似动态查询技术的任何人:
SELECT
with dynamic number of values in IN()
INSERT
dynamic number of rows with one execute()
call
我正在尝试为用户输入编写准备好的语句。参数编号是可变的,取决于用户输入。 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'];
}
}
}
当我print_r($inputArray)
时,输出为:
Array ( [0] => ss [1] => my [2] => name )
错误日志中没有显示错误。
怎么了?
编写通用查询处理程序并将您的查询、参数数组和参数类型列表传递给它。取回一组结果或消息。这是我自己的 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);
}
}
}
?>
%
环绕参数,而不是占位符。
我的代码片段将使用面向对象的 mysqli 语法,而不是您的代码演示的过程语法。
首先你需要设置必要的成分:
- WHERE 子句表达式 -- 由 OR 分隔
- 您的值的数据类型 -- 您的值是字符串,因此请使用“s”
- 准备语句绑定的参数
我打算将#2 和#3 组合成一个变量,以便使用 splat 运算符 (...
) 更简单地“解包”。数据类型字符串必须是第一个元素,然后一个或多个元素将表示绑定值。
作为逻辑包含,如果您的 WHERE 子句中没有条件,则使用准备好的语句没有任何好处;直接查询 table.
代码:(100% 测试/成功代码)
$string = "my name";
$conditions = [];
$parameters = [''];
foreach (array_unique(explode(' ', $string)) as $value) {
$conditions[] = "name LIKE ?";
$parameters[0] .= 's';
$parameters[] = "%{$value}%";
}
// $parameters now holds ['ss', '%my%', '%name%']
$query = "SELECT * FROM info";
if ($conditions) {
$stmt = $conn->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']} and whatever other columns you want</div>";
}
对于寻找类似动态查询技术的任何人:
SELECT
with dynamic number of values inIN()
INSERT
dynamic number of rows with oneexecute()
call