PHP 循环和 MySQL 中的绑定(bind)查询

标签 php mysql sql mysqli

上下文

我正在尝试使用 PHP 和 MySQL 编写一个高效且安全的搜索脚本,这将防止 SQL 注入(inject)尝试。我正在使用 MySQLi 函数套件,并将用户输入专门绑定(bind)到数据库查询。因为用户可能一次搜索多个单词,所以我开发了一种将变量动态绑定(bind)到 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 )

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

最佳答案

我建议使用 JOIN 而不是子查询:

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

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

关于PHP 循环和 MySQL 中的绑定(bind)查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23316838/

相关文章:

sql - 获取某个时间范围内的每小时

java - REST Web服务jpa更新语句

php - 从 PHP 创建动态 PDF(带有表单字段和交互式元素)

javascript - Magento Custom 模块用于 T 恤设计定制

php - “无法为命名路由生成 URL

php - 如何在 PHP 中递归删除目录及其全部内容(文件 + 子目录)?

python - Django 查询优化 - 使用 Itertools

php 用表情图像替换字符串。用mysql表情数据形成数组的问题

php - SQL 字符串与 if 语句的连接

SQL:搜索具有给定值的列列表(在一行中)