我将如何在 PDO 准备好的语句中使用 MySQL 的 NOW()
,或者如何使用它来解决问题,同时记住 Apache 服务器和数据库服务器可能有轻微的当前时间不匹配(几秒钟),或者在极少数情况下可能是时区分开?
我的代码中有以下函数:
try {
$dbh->insert("users", array(
"email" => $email,
"password" => $password,
"salt" => $salt,
"ingame" => $ingame,
"kiosk" => $kiosk
));
} catch (PDOException $ex) {
error($ex);
}
哪个调用:
/**
* Inserts data into a table. Data must be given in key-value pairs.
*
* Example: $dbh->insert("table", array(
* "data1" => $data1,
* "data2" => $data2
* );
*
* @param type $table The table to insert to
* @param type $keyvaluepairs The key-value pairs.
* @return type The statement that this query produced.
*/
public function insert($table, $keyvaluepairs) {
$sql = "INSERT INTO `{$table}` (";
$values_sql = ") VALUES(";
$values = array();
foreach ($keyvaluepairs as $key => $value) {
$sql .= "`${key}`, ";
$values_sql .= "?, ";
$values[] = $value;
}
$query = substr($sql, 0, -2).substr($values_sql, 0, -2).")";
return $this->query($query, $values);
}
哪个调用:
//TODO update documentation to show it also handles associative arrays with bindvalue
/**
* Can be called to create a query. Use either unnamed or named placeholders for the prepared statements.
*
* Example: $dbh->query("INSERT INTO table (data1, data2) VALUES(?, ?)", array($data1, $data2));
*
* @param type $query The input query, including unnamed or named placeholders
* @param type $values The input values. If it's not an array, then it will be an one-element array
* @return type The statement constructed by this query
*/
public function query($query, $values = array()) {
if (!is_array($values)) {
$values = array($values);
}
$statement = $this->dbh->prepare($query);
$statement->setFetchMode(PDO::FETCH_OBJ);
$i = 1;
if (is_assoc($values)) {
foreach ($values as $key => $value) {
$statement->bindValue($key, $value);
}
}
else {
foreach ($values as $value) {
$statement->bindValue($i++, $value);
}
}
$statement->execute();
return $statement;
}
我有这个功能:
function is_assoc($array) {
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
所以这里的问题是我不能使用自定义 MySQL
查询来插入,因为为了简单起见我已经封装了这些查询,但我仍然希望能够插入 NOW ()
不使用 TIMESTAMP
/CURRENT_TIMESTAMP()
。
我希望您理解这个问题需要一个解释性的答案,因为我已经阅读了“正常”答案并表明它们不能满足我的需求。
更新:我已将 const SQL_NOW = 1;
添加到我的 DBH
类中,但是现在我想修改 insert
像这样:
public function insert($table, $keyvaluepairs) {
$sql = "INSERT INTO `{$table}` (";
$values_sql = ") VALUES(";
$values = array();
foreach ($keyvaluepairs as $key => $value) {
if ($value == SELF::SQL_NOW) {
$sql .= "NOW(), ";
}
else {
$sql .= "`${key}`, ";
$values_sql .= "?, ";
$values[] = $value;
}
}
$query = substr($sql, 0, -2).substr($values_sql, 0, -2).")";
return $this->query($query, $values);
}
这可能是一个合适的解决方案,但是我不能使用1
作为SQL_NOW
值,因为如果我想要的话它会失败插入一个整数1
。如果我采用此解决方案,SQL_NOW
会有什么值(value)?甚至可以赋予它没有值(value)吗?
最佳答案
问得好!
这是一个完美的例子,清楚地表明了为什么所有这些众多的 insert()、update()
以及所有其他旨在替代 SQL 的东西在设计上都是错误的 .
NOW() 并不是您将面临的唯一问题。只是因为SQL 并不是一种乍一看那么愚蠢的语言。它是故意发明的。它的可靠性已经经过数十年的验证。这意味着在学习 PHP 的同时编写完整的 SQL 作为练习并不是那么容易。
因此,您能做的最好的事情就是保持 SQL 不变。
您真正需要的是一两个辅助函数。自动化重复性任务。就这些。而 SQL 必须保持原样。这将使您能够使用它的所有功能,包括使用函数、带参数的函数(!)、查询修饰符(例如“INSERT IGNORE”)或扩展语法(例如 JOINS)。
如果您使用 PDO,则不是那么简单但可行。
但是,唯一正确的解决方案是为 SET 语句使用特殊类型的占位符。
$data = array(
"email" => $email,
"password" => $password,
"salt" => $salt,
"ingame" => $ingame,
"kiosk" => $kiosk,
);
$dbh->query("INSERT INTO ?n SET reg = NOW(), ?u","users", $data);
只需一行即可解决所有困惑和许多许多其他问题。
只需一个 query()
方法即可运行您想要的任何查询,甚至是 REPLACE INTO
。
更新。
看看你在做什么!
您计划类(class)是为了简化事情。但目前你正在让它变得越来越复杂。最终,您将得到一个庞大的巨人,其语法不一致,甚至连它的创建者和其他人也几乎无法理解无数的异常。而且仍然不允许您运行一些查询。
请在为时已晚之前重新考虑您的设计。
关于php - PDO 使用 MySQL 的 NOW(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20703218/