【问题标题】:PHP PDO - Bind table name? [duplicate]PHP PDO - 绑定表名? [复制]
【发布时间】:2013-02-17 10:34:09
【问题描述】:

可以绑定表名吗?

我想创建一个类来读取表中的列,并根据字段类型为我生成表单输入。当我执行$form = new form("users"); 时,构造函数应该从使用以下代码从表中获取字段名称开始:

class form{

    public function __construct($table, $skip = array("id")){
        $pdo = new PDO('mysql:host=localhost;dbname=site;',USER,PASS);

        $query = $pdo->prepare("DESCRIBE :table");

        $query->bindValue(':table', $table, PDO::PARAM_STR, strlen($table));

        $query->execute();

        while($field = $query->fetch(PDO::FETCH_NUM)){
            var_dump($field);
            echo "<br /><br />";
        }

        unset($pdo);
    }
}

当我在prepare语句中指定“users”而不是“:table”时,这工作得很好,但是绑定它正在工作,我很确定这是因为它试图绑定一个表名。此外,这需要绑定,因为我希望能够通过$_GET 等传递我的表名。

【问题讨论】:

    标签: php pdo


    【解决方案1】:

    可以绑定表名吗?

    没有。

    您必须将表名列入白名单。我怀疑您是否想让用户从您的数据库中浏览 any 表。

    您还必须手动格式化标识符。 有一个tag wiki 的例子。为什么不先读呢?

    更新: 如您所见,PDO 对现实生活中的任务不方便。 所以,你必须有一个更智能的抽象库来处理 MySQL 查询。 下面是一个使用 safeMysql 类的示例,这将使您的代码大大缩短:

    class form{
        public function __construct($table){
            global $db;
            return $db->getAll("DESCRIBE ?n", $table);
        }
    }
    

    2 个注释:

    • 我删除了第二个参数,因为您的函数中没有使用它的代码。
    • 永远不要在课堂上进行连接。请改用已打开的连接。或者你会用这么多的连接杀死你的 MySQL 服务器。

    排除实施的版本

    class form {
        public function __construct($table,$skip = array("id")){
            global $db;
            $data = array();
            $res = $db->query("DESCRIBE ?n", $table);
            while($row = $db->fetch($res)) {
                if (!in_array($row['Field'],$skip)) {
                    $data[] = $row;
                }
            }
            return $data;
        }
    }
    

    然而,这样的类很少能按预期使用 - 总是有很多例外和手动格式化以使其可用。

    【讨论】:

    • 在那个wiki的'PDO Prepared statements and IN'部分,你为什么不能用表的参数替换SQL字符串?
    • 我不知道有标签维基。这很方便。还有,为什么这样的课会浪费时间?
    • 完成所有编辑后,您的答案更有意义。我将坚持使用一个简单的、无绑定的 PDO 查询,因为它会使用与您提到的类相同数量的语句,并创建一个全局 pdo 变量。此外,该类不是为了让表单从头到尾,它只是为了使用正确的输入类型为您创建输入和标签,使用正确的“for”标签,输入的最大长度等于数据库中字段的最大长度等。就格式而言,只要您保持 HTML 简单,所有格式都可以在 CSS 中轻松完成。
    • @MisterMelancholy 如果它采用完全相同数量的语句,则您没有格式化 $table 变量,因此允许注入。
    • 是的。 “您不想让用户选择他们看到的表格”还有另一个好处。如果我需要将表名列入白名单,我不需要在比较之前清理变量,因为如果它与白名单表名不完全匹配,SQL 查询将不会运行,因此不需要SQL 清理。很抱歉在我之前的评论中跳过了那个小细节。
    【解决方案2】:

    http://www.phpclasses.org/package/5997-PHP-Database-access-abstraction-layer.html 有一个 PDO 包装类,可以让您执行此操作(虽然我是 PDO 新手,所以它可能没有使用准备好的语句)

    他的建议用法是:

     $db = new DatabaseConnection('someMysqlServer', 'user', 'pass', 'database');
    
     $result = $db->exec($db->filterForSql('SELECT * FROM '.$tableName.';'));
    

    如果其他人认为这是使用 PDO 的“安全”方式,我会很感兴趣。

    【讨论】:

    • 无论什么班级做像filterForSql 这样的事情都是不可用的危险废话。该网站需要注册,因此我无法更全面地查看它
    • 我很惊讶你说当你没有阅读源代码时它是无法使用的废话。抱歉,这方面有很多相互矛盾的信息,我有兴趣看到一个“防弹 PDO 数据库类”——你有什么建议吗?
    • 您发布的功能足以判断。 SQL 查询由许多 个不同的部分组成,不可能为它们创建一个通用的过滤器——过滤一个会破坏另一个,相反。我有一个用于运行 mysql 查询的防弹类(虽然不是基于 PDO,但没关系)。您可以在我的个人资料中找到该链接。我所知道的唯一真正的防弹类。
    • 感谢您的课程 - 看起来很有趣。我仍然不相信原始海报要求无法满足。
    • 我已将代码添加到我的答案中。
    猜你喜欢
    • 2012-04-27
    • 2013-01-17
    • 1970-01-01
    • 2011-08-29
    • 2012-06-22
    • 2012-02-15
    相关资源
    最近更新 更多