1

我有一个用于数据库管理的类,我的一个子类(定义查询的那个)是这样定义的(只是一个示例,实际上为了测试目的而剥离了许多其他功能):

namespace Tests\SQL\Arguments {
    // SQL query
    class Query {
        public $attributes;

        // constructor for this object
        public function __construct() {
            if ($arguments = func_get_args()) {
                $this->attributes["query"] = current($arguments);

                if (sizeof($arguments) > 1) {
                    $this->attributes["parameters"] = array_slice($arguments, 1, sizeof($arguments));
                }

                return $this;
            }
        }
    }

    $query = new Query("INSERT INTO `clients/history` (`date`,`client`,`ammount`,`status`) VALUES (?,?,?,?);", date("Y-m-d H:i:s"), 57, 17852.25, "A");
    print_r($query);
}

如您所见,我自动获取函数参数,因此我可以在构建时轻松地将查询与其参数分开。除了批量INSERT/UPDATE/DELETE操作之外,我还想提供一些安全性,比如防止 SQL 注入和其他事情。

我的问题是......给定这个结构,当我传递这个结构时(只是一个简单的例子,它将以不同的方式运行,但这个暂时有效):

$this->queries["clients/history"]->execute($this->attributes["query"], $this->attributes["parameters"]);

(:date,:client,:ammount,:status)使用像这样的命名参数或使用像问号这样的参数会有什么不同(?,?,?,?)吗?

编辑 - 更好的解释

对于我的问题提出的(明显的)晦涩难懂,我深表歉意。我的意图是有一个类似于 sprintf 的机制,但是,我不是存储包含所有参数的字符串,而是以单独的方式存储查询和参数。

这只是 Query 类。还有 QueryGroup 类(用于将查询存储在组中)、Manager 类(存储和管理所有数据库连接)和 Connection 类(负责将给定数据库连接的所有查询和查询组放在一起。

关于命名参数,我认为我使用的方法没有问题,就像我说的那样,就像sprintf函数一样。我将在查询字符串中提供问号或参数名称。

我想进行分离以提供额外的过滤功能,例如转义或引用参数,以防止对给定数据库进行某些形式的注入或破坏。

execute()我公开的方法只是 PDOexecute()方法的纸质副本。我试图确定的是使用命名参数或问号参数是否同样“安全”(或者可能存在一些我没有看到的差异)。

任何提示将不胜感激:)

4

3 回答 3

5

命名参数与未命名参数之间的区别在于,对于未命名参数,您必须注意它们绑定到查询的顺序。

特别是在您的示例中,未命名的参数非常适合,因为它简化了函数调用。


进一步注意,您不需要调用return $this;构造函数方法。

于 2013-04-06T19:01:36.273 回答
1

在您的情况下,它应该没有什么区别。

于 2013-04-06T19:06:12.927 回答
1

虽然没有技术差异(因为 PDO 只会在内部将命名占位符替换为问号),但存在可用性问题

对于类似 sprintf 的函数,问号似乎是更好的解决方案。因为他们会让你使用确实 sprintf 风格(不知道你为什么要为查询创建一个完整的类):

$query = new Query("SELECT * FROM t WHERE a=? AND b=?", $ida, $idb);

而命名它会更加冗长

于 2013-04-06T19:20:23.223 回答