使用 PDO 插入/更新辅助函数
我有一个非常简单的辅助函数来为传统的普通 mysql 驱动程序使用生成 SET 语句:
function dbSet($fields) {
$set='';
foreach ($fields as $field) {
if (isset($_POST[$field])) {
$set.="`$field`='".mysql_real_escape_string($_POST[$field])."', ";
}
}
return substr($set, 0, -2);
}
这样使用
$id = intval($_POST['id']);
$fields = explode(" ","name surname lastname address zip fax phone");
$_POST['date'] = $_POST['y']."-".$_POST['m']."-".$_POST['d'];
$query = "UPDATE $table SET ".dbSet($fields)." stamp=NOW() WHERE id=$id";
它使代码非常干燥、简单但同时又灵活。
我想问是否有人愿意分享类似的功能,利用 PDO 准备好的语句功能?
我仍然怀疑如何实现这一点。
有没有直接简单的方法使用 PDO 准备好的语句插入数据? 应该是什么形式?查询生成器助手?或者插入查询助手?它应该采用什么参数?
我希望它可以很容易地用作此处的答案。因为在每个主题中我们都可以看到准备好的语句用法推荐,但没有一个好的例子。我的意思是,现实生活中的例子。我认为输入20次bind_param()并不是一个好的编程风格。 甚至还有20个问号。
I have a very simple helper function to produce SET statement for traditional plain mysql driver usage:
function dbSet($fields) {
$set='';
foreach ($fields as $field) {
if (isset($_POST[$field])) {
$set.="`$field`='".mysql_real_escape_string($_POST[$field])."', ";
}
}
return substr($set, 0, -2);
}
used like this
$id = intval($_POST['id']);
$fields = explode(" ","name surname lastname address zip fax phone");
$_POST['date'] = $_POST['y']."-".$_POST['m']."-".$_POST['d'];
$query = "UPDATE $table SET ".dbSet($fields)." stamp=NOW() WHERE id=$id";
it makes code quite DRY and easy but flexible at the same time.
I gotta ask if anyone willing to share a similar function, utilizing PDO prepared statements feature?
I am still in doubts, how to accomplish this.
Is there a straight and simple way to use PDO prepared statements to insert data?
What form it should be? Query builder helper? Or insert query helper? What parameters it should take?
I hope it can be easy enough to be used as an answer here on SO. Because in the every topic we can see prepared statements usage recommendation, but there is not a single good example. Real life example, I mean. To type bind_param() 20 times is not a good programming style I believe.
And even 20 question marks too.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
您可以这样扩展 PDO:
You can extend PDO like that:
与其他人一样,我扩展了标准 PDO 类以满足我的需要。类似的东西可能适合您:
然后您可以非常简单地使用它:
Like others I've extended the standard PDO class to suit my needs. Something along the lines of this may suit you:
Then you can use it quite simply:
插入查询通常需要许多占位符。问号样式难以阅读,命名参数重复并且容易出现输入错误。因此,我为整个插入查询创建了一个函数:
用法很简单:
如果您需要
lastInsertId()
:Insert queries often require many placeholders. The question mark style is then hard to read, and named parameters are repetitive and prone to typing errors. So, I created a function for the whole insert query:
Usage is simple:
And if you need
lastInsertId()
:参考:如何防止 PHP 中的 SQL 注入?
Reference: How can I prevent SQL injection in PHP?
我通常有一个扩展 PDO 的类,但我的类是非常自定义的。如果我将其清理并测试,我将在稍后发布。不过,这是针对您的系统的解决方案。
这可能并不完美,可以进行调整。它考虑到
$dbh
是通过 PDO 连接设置的。等待我提出的任何小语法问题,这应该可行。编辑
说实话,我想我会选择 Doctrine ORM(或其他 ORM)。当您设置模型并在其中添加所有验证时,事情就很简单:
这应该可以轻松填充内容。这当然是使用 ORM,比如 Doctrine。
已更新
对第一个代码进行了一些细微调整,例如将
isset
放回原处并在substr
上使用rtrim
。要提供 PDO 扩展类的模型,只需布局实现方式并进行一些单元测试以确保其有效。I usually have a class extending PDO, but my class is pretty custom. If I get it cleaned up and tested I will post it at a later time. Here is a solution to your system, however.
This may not be perfect and could use tweaking. It takes into account that
$dbh
is setup with a PDO Connection. Pending any minor syntax issues I made, that should work.EDIT
Really though, I think I would go for Doctrine ORM (or another ORM). As you setup the model and add all the validation there, then it is as simple as:
That should populate the contents easily. This is of course with an ORM, like Doctrine.
UPDATED
Did some minor tweaks to the first code, such as putting
isset
back and usingrtrim
oversubstr
. Going to work on providing a mock up of a PDO Extension class just gotta layout the way to do it and do some unit tests to make sure it works.谢谢大家。
每个答案都很有帮助,我希望我能分享赏金。
最后,令我惊讶的是,我能够以与以前相同的方式进行制作,基于已接受的答案
它可以包装到辅助函数中,但我怀疑是否有必要。它将把代码缩短一行。
pdoSet代码:
Thanks to everyone.
Every answer was helpful and I wish I could split the bounty.
At the end, to my surprise, I was able to make it the same way as before, based on on accepted answer
It can be wrapped into a helper function, but I doubt there is necessity. It will shorten the code by just one line.
pdoSet code:
我会扩展核心 PDO 类并添加一个像这样的方法:
然后像这样使用
但是正如已经说过的那样,您应该对您尝试做的事情感到非常厌倦,您需要验证您的数据,它已被清理,但您未经验证。
i would extend the Core PDO Class andd a method like so:
Then use like so
But as its already been said that you should be VERY weary of what your trying to do, you need to validate your data, its been sanitized but you not validated.
对于我认为重复出现的参数绑定情况,我一直在修补一些琐碎的事情。
http://fossil.include-once.org/hybrid7/wiki/db
无论如何;它提供了一些替代准备好的语句占位符。您的示例可以缩短为:
这种情况仅适用于命名参数,因此 $set 将是 array("name"=>..) 和 $where=array("id"=>123)。
:,
在您传递的第一个数组上展开。它被替换为逗号分隔的名称=:名称对(这就是它的助记符是:,
的原因)。还有一些占位符
:,
:&
::
和:?
用于不同的用例。只有??
确实有点标准。因此它需要一些时间来适应,但它显着简化了准备好的语句和数组绑定(PDO 本身不这样做)。I've been patching something trivial together for what I consider recurring parameter binding cases.
http://fossil.include-once.org/hybrid7/wiki/db
Anyway; it provides some alternative prepared statement placeholders. Your example could be shortened into:
This case only works with named parameters, so $set would be array("name"=>..) and $where=array("id"=>123). The
:,
gets expanded on the first array you pass. It's replaced with comma-separated name=:name pairs (that's why its mnemonic is:,
).There are a few more placeholders
:,
:&
::
and:?
for different use cases. Only the??
is really somewhat of a standard. So it needs some getting used to, but it significantly simplifies prepared statements and array binding (which PDO doesn't do natively).这是我的通用数据库抽象类。看一下
autoExecute()
函数。它为您想要完成的任何任务提供了大量的灵活性。我应该警告一下,这是为 PHP 5.3 编写的,并且针对 PostgreSQL 进行了轻微的定制。Here's my general database abstraction class. Take a look at the
autoExecute()
function. It offers tons of flexibility for whatever it is you might want to accomplish. I should warn that this was written for PHP 5.3, and has been slightly tailored for PostgreSQL.尽管我的数据库类不使用准备好的语句,但我仍然想在这里提及它。我认为没有理由用准备好的语句来实现所有事情。我确实知道准备好的语句更快,但仅限于多次使用。如果您仅执行一次查询(这是我通常需要使用的唯一查询类型),则它较慢。因此,到处使用准备好的语句会适得其反。
可以找到该类的正确描述stackoverflow 的其他地方。但这里有一些好东西:
DB::instance()->execute
和DB::
用于DB::x
qDB::instance()->query
?
和?x
(其中 < code>x 可以是、
、&
和|
)。?,
占位符可以在此处用作 UPDATE 助手。但有关完整信息,请参阅上面链接的 stackoverflow 帖子;)
PS:存储库中的自述文件不适用于此类。它适用于普通的
DB.php
,而不适用于DB_intelligent.php
。PPS:该类是为 PHP 5.3 编写的。如果您想在 PHP 5.2 上使用它,只需将所有这些 PDO 方法从
DB_forPHP52.php
复制到DB_intelligent.php
并删除__callStatic
方法。Even though my DB class does not use prepared statements I still want to mention it here. I see no reason at all to implement everything with prepared statements. I do know that prepared statements are faster, but only when used multiple times. If you execute the query only once (and this is the only type of query I normally need to use), it is slower. Thus it is counterproductive to use prepared statements everywhere.
Proper description of the class may be found some place else at stackoverflow. But here some of the good stuff:
DB::x
forDB::instance()->execute
andDB::q
forDB::instance()->query
?
and?x
(wherex
may be,
,&
and|
). The?,
placeholder may be used as an UPDATE helper here.But for full information see the stackoverflow post linked above ;)
PS: The README in the repo does not apply to this class. It is for the normal
DB.php
, not forDB_intelligent.php
.PPS: The class is written for PHP 5.3. If you want to use it on PHP 5.2 simply copy all those PDO methods from
DB_forPHP52.php
toDB_intelligent.php
and remove the__callStatic
method.除了其他答案之外:正确引用列名的方法:
Just in addition to other answers: a method for proper quote of column names: