使用PDO查询,不使用预处理语句,使用来自多个HTML输入字段的多个LIKE语句


Using PDO query, without prepared statements, with multiple LIKE statements from multiple HTML input fields

我已经成功地在PDO中执行和打印查询,但我在这里做错了。这个问题的重要代码部分在最后几块代码中;为了清楚起见,我把第一部分包括在内。

这段代码连接到一个带有多个输入字段的HTML表单。PHP通过在WHERE语句中给每个字段的数据附加and来构造查询。

这是让我困惑的:我回显$query变量,我可以看到查询是正确形成的,但是当我试图打印查询结果时,没有打印结果。

我纠结于在这里使用准备好的语句,并决定在构造具有不同数量参数的准备好的语句失败后,首先尝试让代码在没有准备好的语句的情况下工作。我确实尝试过,在这篇文章的帮助下:使用PDO准备好的语句从搜索字段使用多个关键字进行LIKE查询

那么,暂时把准备好的语句放在一边,谁能告诉我我在这里做错了什么?如有任何帮助,我将不胜感激。

<?php
if(isset($_POST['submit'])) {
// define the list of fields
$fields = array('titleSearch', 'keywordSearch', 'fullSearch', 'fromYear', 'toYear', 
    'fromSeconds', 'toSeconds', 'withSound', 'withColor');
$conditions = array();
// loop through the defined fields
foreach($fields as $field){
    // if the field is set and not empty
    if(isset($_POST[$field]) && $_POST[$field] != '') {
        // create a new condition, using a prepared statement
        $conditions[] = "$field LIKE CONCAT ('%', $_POST[$field], '%')";
    }
}
// build the query
$query = "SELECT keyframeurl, videoid, title, creationyear, sound, color, 
     duration, genre FROM openvideo ";
// if there are conditions defined, append them to the query
if(count($conditions) > 0) {
    $query .= "WHERE " . implode(' AND ', $conditions);
}
//confirm that query formed correctly
echo $query; 
//print query results
foreach ($dbh->query($query) as $row){
   print $row['videoid'].' - '.$row['title'].'<br />';
}
}
?>

你必须运行 it而不是张贴你的查询。
这是解决问题的唯一方法

  • 一个堆栈溢出的过路人没有一个数据库服务器在他们的头脑中运行你的查询。
  • 一个堆栈溢出的过路人没有你的特定的数据库服务器在他们的头运行你的查询。

所以,你是唯一一个可以对数据库运行你的查询并问它出了什么问题的人。

  1. 打开错误报告。确保您可以看到发生的错误。尝试添加故意错误,看看它是否有效。
  2. 仔细检查你的数据库数据,如果它真的包含所需的值。
  3. 仔细检查你的输入数据,如果它真的符合数据库值。
  4. 在控制台或phpadmin中对数据库运行已组装的查询。

深入研究某个问题。不要只是坐着等待。问一个问题"我有一个不能工作的代码"是没有意义的。代码必须运行,而不是盯着看。

$conditions[] = "$field LIKE CONCAT ('%', $_POST[$field], '%')";

是罪魁祸首:为标题发送的"某事"最终以

之类的内容结束。
WHERE titleSearch LIKE CONCAT('%', something, '%')

但是你想

WHERE titleSearch LIKE CONCAT('%', 'something', '%')

加引号

请确保不要将此应用到生产环境中,因为您最终可能会看到有人发布"xxx")OR 1=1;——"只是为了表演的乐趣,或者更糟,取决于他们的心情。

您忘记了直接插入到查询中的$_POST值周围的引号:

$conditions[] = "$field LIKE CONCAT ('%', '$_POST[$field]', '%')";
                                          ^--            ^--

因此,虽然这将解决您的直接问题,但您仍然会受到SQL注入攻击。

您甚至不需要CONCAT内置函数,您可以将整个字符串建模为$conditions[] = "{$field} LIKE '%{$_POST[$field]}%'"。但是如果你不想在短期内面临严重的SQL注入攻击,你应该使用准备好的语句。

你为什么不试试这样的东西呢?(以PDO为例):

if ($pdo = new 'PDO("mysql:host=localhost;dbname=testdb;charset=utf8", "user", "password")) {
    $fields = ["titleSearch","keywordSearch","fullSearch","fromYear","toYear","fromSeconds","toSeconds","withSound","withColor"];
    $parameters = array_map(function ($input) { return filter_var($input, FILTER_SANITIZE_STRING); }, $fields)
    $conditions = array_map(function ($input) { return (!empty($_POST[$input]) ? "{$input} LIKE ?" : null); }, $fields);
    $query = "SELECT `keyframeurl`,`videoid`,`title`,`creationyear`,`sound`,`color`,`duration`,`genre` FROM `openvideo`" . (sizeof($conditions) > 0 ? " " . implode(" AND ", $conditions) : null);
    if ($statement = $pdo->prepare($query, ['PDO::ATTR_CURSOR => 'PDO::CURSOR_FWDONLY])) {
        if ($statement->execute((!empty($parameters) ? $parameters : null))) {
            $result = $statement->fetchAll('PDO::FETCH_ASSOC);
        }
    }
}

还没有测试过它(刚刚想到我现在),但它应该设置PDO,根据您似乎要寻找的条件准备一个语句,在execute()方法中添加参数(预过滤,虽然有FAR更好的过滤技术),并返回与您的查询相关的所有结果。

即使你决定不使用这个,至少给它一个想法…这是PDO的一个很好的起点,当然,还可以获得一个关于get/POST变量过滤的很好的教程(或者使用第三方工具,如HTML净化器)。

希望有帮助;)