【问题标题】:PDO Prepared Statement FunctionPDO 准备好的语句函数
【发布时间】:2014-07-20 08:43:11
【问题描述】:

我正在使用 PDO 准备好的语句,在处理我当前的项目时,我决定为我需要的每个操作创建几个函数。下面是 fetch 的例子

function db_fetchAll($sql, $param) {
    global $db;

    $stmt = $db->prepare($sql);

    if (empty($param)) {
        $stmt->execute();
    } else {
        $stmt->execute($param);
    }

    $count = $stmt->rowCount();

    if ($count == 0) {
        $result = "";
    } elseif ($count == 1) {
        $result[] = $stmt->fetch();
    } elseif ($count > 1) {
        $result = $stmt->fetchAll();
    }

    return $result;
}

例子

$database = db_fetchAll("SELECT * FROM database_table WHERE id=:id", array(':id' => $id));

它只将查询的行数从 3 行压缩到 1 行,但是对于每个页面所需的信息量,它值得压缩。

我将返回该项目进行最后一次通过,我只是想就其安全性提出第二意见。如果有什么我应该添加的,等等。所有 user_input 都通过这个函数传递

function user_input($input) {
    $input = trim($input);  
    $output = strip_tags($input);

    return $output;
}

所有输出都使用 htmlspecialchars。

所以简而言之,问题是: 这安全吗? 我还能做些什么来防止任何其他形式的注射等?

我完全理解准备好的陈述是如何工作的,我只是说得透彻,这个网站的第 1 版是一场噩梦,大量的注入,获得对管理员帐户的访问权限等等。

【问题讨论】:

  • 你在问什么?你问安全吗?您正在使用准备好的语句,并且您正在正确使用它们……没关系。
  • 是的,这就是问题所在,我进行了编辑以使事情更清晰。
  • 您可能需要检查$stmt->execute(); 的返回值是否有错误。
  • 您说得对,常识先生,例如他可能希望 PDO 抛出异常。
  • 在生产模式期间(在全局文件中定义)不会抛出错误(error_reporting(0))它们只是被记录下来。同样对于依赖于特定查询的页面(例如用户配置文件),如果函数返回空,则页面将重定向到 404。在仅显示信息的其他页面上,如果函数返回空,则信息将保持隐藏状态。

标签: php pdo


【解决方案1】:

+1 表示这样的意图。一个相当尴尬的数字,但在这里询问有关 PDO 的问题的用户中只有万分之一会想到像辅助函数这样自然的事情。

只是一些笔记。

  • 首先,您的代码存在一个基本缺陷,即试图自动检测结果类型。我自己试过了,我可以向你保证,这只是灾难的根源。你的代码中的魔法越少,你头上的头发就越多。因此,不要使用这种不可靠的魔法,只需制作不同的函数来返回不同的结果集即可。
  • 其次,你必须为参数设置默认值吗?能够在没有占位符的情况下运行查询。
  • 第三,有些代码是多余的。无需检查 $param 变量。

最后,你的函数应该是这样的

function db_fetchAll($sql, $param = array()) {
    global $db;

    $stmt = $db->prepare($sql);
    $stmt->execute($param);
    return $stmt->fetchAll();
}

并且顾名思义总是返回行数组

与具有不同结果集的其他函数一样,PDO 似乎只要稍微调整一下,就可以提供完全相同的便利,而无需任何辅助函数。你可以看看PDO wrapper I made to ease the pain of transition from old mysql ext

您的代码将几乎保持不变

$data = DB::query("SELECT * FROM database_table")->fetchAll();

但它会让你使用 PDO 不同结果集方法的所有装腔作势:

$row = DB::prepare("SELECT * FROM table WHERE id=?")->execute([$id])->fetch();

甚至

$sql  = "SELECT name FROM table WHERE id=?";
$name = DB::prepare($sql)->execute([$id])->fetchColumn();

等等

【讨论】:

  • 所以切换到第二个建议更倾向于避免使用帮助器对吗?整个网站是完整的,如果它是一个偏好并且不提供任何额外的好处,那么我最终会坚持使用助手。我删除了我不知道为什么我在每个助手中使用它的计数。我不希望错误出现在用户端,所以我会考虑关闭错误报告但保留日志,(我以为我已经设置了,但我显然没有)谢谢你的帮助。
  • 看来你没有明白重点。嗯,你会从经验中学习的。
猜你喜欢
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 2011-07-13
  • 2017-09-29
  • 2016-12-30
  • 2010-11-05
相关资源
最近更新 更多