我有一个AJAX函数,每隔x次调用数据库中的新内容就会调用fetchPosts()
(PHP)。
该函数按预期工作,不传递任何参数( - 在这种情况下,它返回数据库中的所有行,如下所示),但是当我传递用于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();
}
...
}
我从另一个函数调用该函数。
function debugOnlyShowNew() {
$lastuseractivity= $_SESSION['lastuseractivity'];
fetchPosts('timestamp', '>', $lastuseractivity);
}
_SESSION['lastuseractivity']
在几个事件上被(重新)定义为date ("Y-m-d H:i:s")
,并且从两个函数中正确地回应。所有时区都是正确的(PHP和MySQL)。
session_start
位于function.php之上,其中debugOnlyShowNew()
和fetchPosts()
都已定义。
timestamp
是一个DATETIME
MySQL列
以下查询正常工作并按预期返回新内容:
SELECT * FROM messages WHERE hidden=FALSE AND timestamp > '2014-01-28 15:24:00' ORDER BY id DESC
是什么给出了?
答案 0 :(得分:0)
您无法直接执行此操作,因为PDO不允许您绑定运算符或列等内容。您必须通过将字符串连接在一起来构建SQL。如果这样做,请确保白名单条件和运算符。我建议您尝试使用某些东西以编程方式与您的数据库进行交互,例如RedBean:http://www.redbeanphp.com/
尽管如此,这里有一个可行的例子,但仍然是安全的(虽然不是很容易维护):
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...
}
答案 1 :(得分:0)
这样:
$stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE AND :cond :oper :val ORDER BY id DESC");
无法运行。
:cond
参数旨在包含针对数据库中字段的值,而不是查询的字词。当您prepare()
PDOStatement时,将评估查询,并且sql将在:cond :oper :val
发生错误,因为这绝不是有效的sql语法。了解当你准备一个语句时,不会评估这些值(这就是为什么它实际上可以防止sql注入)
但你可能会这样做:
$cond = 'field';
$oper = '=';
$stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE AND $cond $oper :val ORDER BY id DESC");
这将准备此声明:
$stmt = $pdo->prepare("SELECT * FROM messages WHERE hidden=FALSE AND field = :val ORDER BY id DESC");
$stmt->execute(array(":val" => $val));
这是有效的,仍然可以让你有一个“动态”的SQL语句