我有一个用于数据库管理的类,我的一个子类(定义查询的子类)是这样定义的(只是一个示例,许多其他函数实际上被剥离用于测试目的):
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()
方法只是PDO的execute()
方法的纸质副本。我试图确定的是,使用命名参数或问号参数是否同样“安全”(或者可能存在一些差异,我没有看到)。
任何提示都将不胜感激:)
答案 0 :(得分:5)
命名的未命名参数之间的区别在于,对于未命名的参数,您必须注意它们将与查询绑定的顺序。
特别是在你的例子中,未命名的params非常适合,因为它可以简化函数调用。
进一步请注意,您无需在构造函数方法中调用return $this;
。
答案 1 :(得分:1)
在你的情况下它应该没有区别。
答案 2 :(得分:1)
虽然没有技术差异(因为PDO会在内部将命名占位符替换为问号),但是存在可用性问题
对于类似sprintf的函数问号似乎是一个更好的解决方案。因为他们会让你使用sprintf风格(不知道你为什么要为查询创建一个完整的类):
$query = new Query("SELECT * FROM t WHERE a=? AND b=?", $ida, $idb);
虽然命名它会更加冗长