MySQL中的PHP循环和绑定查询

MySQL中的PHP循环和绑定查询,php,mysql,sql,mysqli,Php,Mysql,Sql,Mysqli,上下文 我正在尝试使用PHP和MySQL编写一个高效、安全的搜索脚本,以防止SQL注入尝试。我正在使用MySQLi函数套件,专门将用户输入绑定到数据库查询。因为用户可能一次搜索多个单词,所以我开发了一种方法,可以将变量动态绑定到MySQLi查询,但却陷入了一个特定的位置 我有一个用户示例表和一个用户所有技能表: USERS: SKILLS: ID | Username Userid | Skill 1 | Patty 1

上下文

我正在尝试使用PHP和MySQL编写一个高效、安全的搜索脚本,以防止SQL注入尝试。我正在使用MySQLi函数套件,专门将用户输入绑定到数据库查询。因为用户可能一次搜索多个单词,所以我开发了一种方法,可以将变量动态绑定到MySQLi查询,但却陷入了一个特定的位置

我有一个用户示例表和一个用户所有技能表:

USERS:               SKILLS:
ID | Username        Userid  | Skill
1  | Patty           1       | Decorating
2  | Billy           1       | Renovating
                     2       | Painting
                     2       | Flooring
我生成了一个搜索查询,它分解了访问者搜索的所有搜索词,然后通过MYSQLi查询运行它们:

$searched = explode (' ', stripslashes ($search)); // What the visitor searched for

$bindParam = new BindParam (); // Initiate the dynamic binding class
$qArray = array (); 

foreach ($searched as $sd) {    
    $sd = trim ($sd);   
    if ($sd != '') {
        $qArray[] = 'skills.skill LIKE CONCAT(?,\'%\')'; // Use arrays to construct part of the dynamic query
        $bindParam->add ('s', $sd); // Users are searching for strings so use 's' as opposed to 'i' for integer for example
    }
}

$query = "SELECT username FROM users WHERE users.id IN (SELECT skills.userid FROM skills WHERE ";
$query .= implode (' OR ', $qArray);
$query .= ")"; // Join the query together

$stmt = $mysqli->prepare ($query) or die ("Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error);    
call_user_func_array (array ($stmt, "bind_param"), $bindParam->get ()); // Bind the variables to the query

$stmt->execute ();
$stmt->store_result ();

if ($stmt->num_rows > 0) {              
    $stmt->bind_result ($username);
    $searchoutput = array ();
    while ($stmt->fetch ()) {
        $searchoutput[] = $username; // send all usernames to an array      
    }

print_r ($searchoutput); // print all contents of the array

}
问题

现在,当访问者搜索“装饰翻新绘画”时,代码返回:

Array ( [0] => patsy [1] => billy )
…因为MySQL查询实际上忽略了Patsy出现两次的事实。理想情况下,我希望阵列实际显示:

Array ( [0] => patsy [1] => patsy [2] => billy )

除非我根据搜索词的数量将查询合并到一个循环中,否则我如何解决这个问题?

我建议使用联接,而不是子查询:

SELECT username FROM users 
JOIN skills ON users.id=skills.userid
WHERE
skills.skill LIKE CONCAT(?,\'%\')
OR skills.skill LIKE CONCAT(?,\'%\')
OR ...

当用户名与多种技能匹配时,应多次显示用户名。

查看最终执行的查询文本。这是这里唯一重要的事情,完美地解释了行为:
a或a或b
a或b
(as
a或a->a
)相同。SQL正按照您告诉它的方式进行操作,所以从最后的查询文本开始。(很好地避免了SQL注入,顺便说一句)。我不太清楚为什么/如何让“patsy/patty”出现多次。如果可能的话,我会使用PDO。您使用PRO进行的查询看起来像“select*from tablename where id=?”,您必须传递一个带有每个问号的值的数组,例如数组(1)。@user2864740原因是,它们出现的次数越多,我就越容易根据匹配的数量来重新组织数组。就我所理解的问题而言,帕蒂应该出现两次,因为她有两项技能。这绝对正确。是的,你的答案绝对完美!非常感谢。