【发布时间】:2015-05-28 09:25:36
【问题描述】:
在尝试构建健壮的数据库代码(表锁定、事务等)时,我总是对需要完成的大量代码感到恼火。
例如,两个准备好的语句中的一个事务,我想删除一个用户并在“操作”表中更新关于他的一些内容:
- 锁定表用户、操作
- 启动事务(自动提交 false)
- 为删除用户制作准备好的语句
- 检查语句是否为 != false(因为它可能在 3 处已经失败。
- 绑定参数
- 检查语句中的 errorState != "00000"(绑定参数也可能失败)
- 执行语句
- 检查语句上的 errorState != "00000"(也可能执行失败)
- 获取语句结果
- 结束声明
- 为更新操作创建一个新的准备好的语句
- 检查 if 语句 != false
- 绑定参数
- 检查语句的错误状态
- 执行
- 检查语句的错误状态
- 得到结果
- 结束声明
- 检查整体事务状态,如果有效提交,如果无效回滚
- 解锁表
- 将自动提交设置回 true
我就是这样做的(也许我做错了?)。如果我这样做,它的工作量很大,而且很烦人。所以我想把这些东西自动化。
我想要的是这样的:
$DB->startTransaction();
$DB->query($query);
$DB->query($query2);
$DB->query($query3);
$DB->endTransaction();
在内部,mysqli 之上的数据库抽象层将负责表锁定、准备好的语句和事务本身。我们不应该能够自动化吗?
这是我的尝试之一:
public function query($query, $table, $params = null) {
if($params == null) {
$this->connection->query("LOCK TABLES $table WRITE");
$query = str_replace("!", $table, $query);
$result = $this->connection->query($query);
$this->connection->query("UNLOCK TABLES");
return $result;
}
else {
if (!$this->checkParams($query, $params)) {
return false;
}
$this->connection->query("LOCK TABLES $table WRITE");
$query = str_replace("!", $table, $query);
$stmt = $this->connection->prepare($query);
if ($stmt != false) {
$typesString = "";
foreach ($params as $param) {
if (is_numeric($param)) {
$typesString .= "i";
} else if (is_double($param)) {
$typesString .= "d";
} else {
$typesString .= "s";
}
}
$finalParamArray = array($typesString);
$finalParamArray = array_merge($finalParamArray, $params);
call_user_func_array(array($stmt, "bind_param"), $this->ref($finalParamArray));
$this->checkStatement($stmt);
$stmt->execute();
$this->checkStatement($stmt);
$result = $stmt->get_result();
$stmt->close();
$this->connection->query("UNLOCK TABLES");
return $result;
}
$this->query("UNLOCK TABLES");
return false;
}
}
这可以像这样调用:
$DB->query("DELETE FROM ! WHERE userID =?", "Users", array($userID));
然而,我对此没有信心。我用谷歌搜索了一下,没有找到我想要的东西。所以我现在的问题是:我想要的东西真的可能吗(应该是)?我做错了吗?
编辑: 我还有其他 2 次尝试这样做,看起来要复杂得多(300 多行代码)。如果你愿意,我也可以发布它们。但是,我仍然对它们不满意,并且不确定这是否真的正确!
【问题讨论】:
-
为什么不使用现有的解决方案,例如 Doctrine DBAL?
-
我用谷歌搜索了类似的东西。我很惊讶我没有找到它。谢谢,会用的。