【问题标题】:Is it bad practise to use a general function to query a database? [closed]使用通用函数查询数据库是不好的做法吗? [关闭]
【发布时间】:2013-06-23 17:34:42
【问题描述】:

我正在编写一个网络应用程序,该应用程序将在内部用于各种任务。 它使用一个 MySQL 数据库,该数据库需要定期查询数据。

我知道准备好的语句,它们是最佳实践,但考虑到大量的表和连接,我发现编写一个接受查询、运行并返回结果的通用函数是最简单的。

我知道如果它在实时站点上,它可能容易受到 SQL 注入的攻击,但是使用这种方法有什么固有的坏处吗?我对 php 和 MySQL 之间的接口比较陌生,并且有兴趣了解在 webapp 中运行语句的可重复方法的最佳实践。

这是我将用于SELECT 查询的示例函数。

function getSQLResultsPDO($query){
  $mydb = new PDO('mysql:host=localhost;dbname=mydatabase;charset=utf8', 'user', 'password');
  $sth = $mydb->prepare($query);
 if (!$sth) {
    echo "\n<pre>PDO::errorInfo():</pre>\n";
    echo "<pre>";
    print_r($conn->errorInfo());
    echo "</pre>";
}
  $sth->execute();

  $result = $sth->fetchAll(PDO::FETCH_CLASS);
  if (empty($result)){
    $result = false;
  }

  return $result;

}

【问题讨论】:

  • 这不是关于 SQL 注入,而是关于语法正确性! The Great Escapism (Or: What You Need To Know To Work With Text Within Text)
  • 你真的为每一个查询创建一个新的连接吗?
  • @jay 仅当抛出的异常按原样转储到屏幕时。情况不一定如此。如果您在方法内捕获异常,那么首先抛出它没有真正意义。他甚至没有使用异常错误模式。
  • @Bartdude:完全可以注入自己,没有任何“用户”数据接近查询。 任何进入查询的外部数据都可以是注入源,无论它来自远程用户表单提交,甚至是您之前从数据库中选择的数据。
  • @Bartdude 请阅读有关该主题的内容。准备好的陈述是必须的。没有理由。没有例外。没有冗长的考虑“这些数据是否安全”。另请阅读此处的第一条评论。

标签: php mysql database pdo


【解决方案1】:

我只能同意@jay harris 的评论:“关于该脚本的一切都是不好的做法”

虽然想法使用这样的函数来处理数据库是唯一明智的选择,但实现都是错误的。

首先,您为什么认为拥有这样的函数与准备好的语句相矛盾?为什么不添加一个额外的参数 - 一个包含数据的数组 - 并兼具功能和安全性?

接下来,正如您已经被告知的那样,不要连接每个查询,而是每个应用程序一次

最后,你的错误处理方式是错误的。

function getSQLResultsPDO($query, $params = array(), type = PDO::FETCH_CLASS){
  global $mydb;
  $sth = $mydb->prepare($query);
  $sth->execute($params);
  return $sth->fetchAll($type);
}

虽然不是很方便,但至少好用,安全95%。

使用这个功能一段时间后,你会发现只有一个很不方便。最终你会发现你需要一组函数。一种用于运行不返回行的 DML 查询,以及一些返回不同类型结果的函数。

比较这两个代码:

$data = getSQLResultsPDO("SELECT name FROM users WHERE id=?", array($id));
if (isset($data[0]->name)) {
    $name = $data[0]->name;
}
//and
$name = getSQLscalar("SELECT name FROM users WHERE id=?", array($id));

【讨论】:

  • 感谢您的回答。我现在对这个主题有了更多的了解。我实际上已经向前迈进了一步,开始编写自己的使用 PDO 的类,其中包含 __construct() 方法中的连接内容,然后我可以通过它调用各种查询方法。
【解决方案2】:

这可能是一个很好的做法。如果您查看框架,它们实现了类似的东西,只是它更复杂,并且它们允许您使用不同的方法创建查询。这样做的目的是集中查询,如果所有查询都经过相同的路径,则更容易修改涉及所有查询的内容。例如,如果您想将数据库从 MySQL 更改为其他数据库。此外,您可以在这个中心点防御注射。

所以,你的想法很好,但当然还有一些可以改进的地方。您可以在打开应用程序时创建一个连接,并将其用于以后运行的每个查询。如果您的查询方法在类中,则连接可以是类属性,例如,在构造函数中初始化。

我的建议是看看其他人是如何做到的,并从中获得灵感。例如,看看框架如何处理这些东西。

另外,有一个很好的 MVC 教程也谈到了这些东西,这里是:

http://johnsquibb.com/tutorials

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 2014-08-24
    • 2016-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多