简体   繁体   English

通过多个PHP变量传递SQL WHERE子句

[英]Passing SQL WHERE clause with multiple PHP variables

I have an AJAX function that calls fetchPosts() (PHP) every x amount of time polling for new content in the database. 我有一个AJAX函数,每x轮询数据库中的新内容, fetchPosts()调用fetchPosts() (PHP)。

The function works as intended without any arguments being passed to it (--in that case it returns all rows from the database, as seen below), but it will not work when I pass the variables intended for the MySQL WHERE clause. 该函数按预期运行,而没有传递任何参数(在这种情况下,它将返回数据库中的所有行,如下所示),但是当我传递给MySQL WHERE子句的变量时,该函数将不起作用。

function fetchPosts($cond = NULL, $oper = NULL, $val = NULL) {
    global $PDOhost, $PDOusn, $PDOpwd, $PDOdb;
    $pdo = new PDO("mysql:host=$PDOhost;dbname=$PDOdb", $PDOusn, $PDOpwd);

    if (isset($cond, $oper, $val)) {
        $stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE AND :cond :oper :val ORDER BY id DESC");
        $stmt->execute(array(
            ':cond' => $cond,
            ':oper' => $oper,
            ':val' => $val
            ));
    } else {
        $stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE ORDER BY id DESC");
        $stmt->execute();
    }
    ...
}

I'm calling the function from a different function. 我正在从其他函数调用该函数。

function debugOnlyShowNew() {
    $lastuseractivity= $_SESSION['lastuseractivity'];
    fetchPosts('timestamp', '>', $lastuseractivity);
}

_SESSION['lastuseractivity'] is (re)defined as date ("Ymd H:i:s") on several events and echoes correctly from both functions. _SESSION['lastuseractivity']在多个事件上被(重新)定义为date ("Ymd H:i:s") ,并且从两个函数正确地回显。 All timezones are correct (PHP and MySQL). 所有时区都是正确的(PHP和MySQL)。

session_start is right on top of function.php where both debugOnlyShowNew() and fetchPosts() are defined. session_start就位于function.php的顶部,在其中定义了debugOnlyShowNew()fetchPosts()

timestamp is a DATETIME MySQL column timestampDATETIME MySQL列

The following query works fine and returns new content as expected: 以下查询工作正常,并按预期返回新内容:

SELECT * FROM messages WHERE hidden=FALSE AND timestamp > '2014-01-28 15:24:00' ORDER BY id DESC

What gives? 是什么赋予了?

You can't do this directly because PDO won't allow you to bind things like operators or columns. 您不能直接执行此操作,因为PDO不允许您绑定诸如运算符或列之类的内容。 You would have to build your SQL by concatenating strings together. 您将必须通过将字符串串联在一起来构建SQL。 If you do this, be sure to white list conditions and operators. 如果这样做,请确保将条件和运算符列入白名单。 I would recommend that you try to use something to programatically interact with your DB, such as RedBean: http://www.redbeanphp.com/ 我建议您尝试使用某种方式与您的数据库进行编程交互,例如RedBean: http : //www.redbeanphp.com/

Nevertheless, here is an example of something that could work and still be safe (although not very maintainable): 不过,这是一些可行且仍然安全(尽管不是很容易维护)的示例:

function fetchPosts($cond = NULL, $oper = NULL, $val = NULL) {
    global $PDOhost, $PDOusn, $PDOpwd, $PDOdb;
    $pdo = new PDO("mysql:host=$PDOhost;dbname=$PDOdb", $PDOusn, $PDOpwd);
    // whitelist allowed operators
    $validOperators = Array('<','=','>','<>');
    if (!$oper || !in_array($oper, $validOperators) {
         $oper = null;
    }
    // whitelist allowed columns, conditions, etc.
    $validConditions = Array('col1','col2','col3');
    if (!$cond || !in_array($cond, $validConditions) {
         $cond = null;
    }
    $sql = 'SELECT * FROM messages WHERE hidden=FALSE';
    if (isset($cond, $oper, $val)) {
        $sql .= ' AND '.$cond.' '.$oper.' :val'; 
        $params = Array(':val' => $val);
    } else {
        $params = null;
    }
    $sql .= ' ORDER BY id DESC';
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    // do more stuff with results here...
}

this: 这个:

$stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE AND :cond :oper :val ORDER BY id DESC");

can't run. 不能跑

:cond parameters are intended to contain values targeted at fields in your database, not as words for the query. :cond参数旨在包含针对数据库中字段的值,而不是查询的单词。 When you prepare() your PDOStatement, the query will be evaluated, and sql will bug at :cond :oper :val because that is in no way a valid sql syntax. 当您prepare()您的PDOStatement时,将对查询进行评估,并且sql将在:cond :oper :val因为这绝对不是有效的sql语法。 understand that when you prepare a statement, the values are not evaluated (this is why it actually protects against sql injection) 理解当您准备一条语句时,不会评估值(这就是为什么它实际上可以防止sql注入的原因)

but you might do something like this: 但您可能会执行以下操作:

$cond = 'field';
$oper = '=';
$stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE AND $cond $oper :val ORDER BY id DESC");

this will prepare this statement: 这将准备以下语句:

$stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE AND field = :val ORDER BY id DESC");
$stmt->execute(array(":val" => $val));

which is valid and still gives you the possibility of having a "dynamic" sql statement 这是有效的,但仍然使您拥有“动态” sql语句的可能性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM