2

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

此代码连接到具有多个输入字段的 HTML 表单。PHP 通过在 WHERE 语句中使用 AND 附加来自每个字段的数据来构造查询。

这就是我的想法:我回显了 $query 变量,我可以看到查询的格式正确,但是当我尝试打印查询结果时,没有打印任何结果。

我在这里与使用准备好的语句搏斗,并决定在未能构造具有不同数量参数的准备好的语句后尝试让代码在没有它们的情况下首先工作。在这篇文章的帮助下,我确实尝试过:LIKE query using multiple keywords from search field using PDOprepared statement

所以,暂时搁置准备好的陈述,谁能告诉我我在这里做错了什么?任何帮助将不胜感激。

<?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 />';
}
}
?>
4

4 回答 4

1

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

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

因此,虽然这将解决您的直接问题,但您仍然对 sql 注入攻击持开放态度。

于 2013-04-09T18:54:21.120 回答
1

而不是发布您的查询,您必须运行它。
这是解决问题的唯一方法

  • Stack Overflow 路人的头脑中没有数据库服务器来运行您的查询。
  • Stack Overflow 路人在他们的脑海中没有您的特定数据库服务器来运行您的查询。

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

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

挖掘一些特定的问题。不要只是坐着等待。问一个问题“我有一个不起作用的代码”没有什么意义。代码必须运行,而不是盯着看。

于 2013-04-09T19:54:31.507 回答
0
$conditions[] = "$field LIKE CONCAT ('%', $_POST[$field], '%')";

是罪魁祸首:为标题发送“某事”最终会变成类似

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

但你想要

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

有更多的报价。

但是请务必不要将其推广到生产中,因为您可能最终会发布“xxx') OR 1=1; --”只是为了表现的乐趣,或者更糟糕的是,取决于他们的心情。

于 2013-04-09T18:56:42.693 回答
-1

您甚至不需要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 这样的 3rd-party 工具净化器,就此而言)。

希望有帮助;)

于 2013-04-09T20:11:15.273 回答