Preg_replace 准备语句的解决方案

发布于 2024-08-04 09:15:10 字数 703 浏览 2 评论 0原文

我有一个命令类,它抽象了几乎所有特定的数据库功能(我们在 Mssql 2005(使用 ODBC 和本机 mssql 库)、MySQL 和 Oracle 上运行完全相同的应用程序。但有时我们的准备方法会遇到一些问题,当执行后,将所有占位符替换为各自的值。但问题是我使用以下内容:

if(is_array($Parameter['Value']))
{
    $Statement = str_ireplace(':'.$Name, implode(', ', $this->Adapter->QuoteValue($Parameter['Value'])), $Statement);
}
else
{
    $Statement = str_ireplace(':'.$Name, $this->Adapter->QuoteValue($Parameter['Value']), $Statement);
}

当我们有两个或多个相似的参数名称时,例如 session_browser 和 session_browse_version ...第一个将部分替换最后一个。

当然,我们学会了在特定顺序内指定参数,但现在我有一些“空闲”时间,我想做得更好,所以我正在考虑切换到 preg_replace...但我做得不好在正则表达式中,任何人都可以提供任何有关正则表达式的帮助来替换像 ':parameter_name` 这样的字符串

最好的问候, 布鲁诺·BB·马加拉斯

I have a command class that abstracts almost all specific database functions (We have the exactly same application running on Mssql 2005 (using ODBC and the native mssql library), MySQL and Oracle. But sometimes we had some problems with our prepare method that, when executed, replaces all placeholders with their respective values. But the problem is that I am using the following:

if(is_array($Parameter['Value']))
{
    $Statement = str_ireplace(':'.$Name, implode(', ', $this->Adapter->QuoteValue($Parameter['Value'])), $Statement);
}
else
{
    $Statement = str_ireplace(':'.$Name, $this->Adapter->QuoteValue($Parameter['Value']), $Statement);
}

The problem arises when we have two or mer similar parameters names, for example, session_browser and session_browse_version... The first one will partially replace the last one.

Course we learned to go around specifying the parameters within a specific order, but now that I have some "free" time I want to make it better, so I am thinking on switching to preg_replace... and I am not good in regular expression, can anyone give any help with a regex to replace a string like ':parameter_name`?

Best Regards,
Bruno B B Magalhaes

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娇纵 2024-08-11 09:15:10

您应该使用 \b 元字符 来匹配单词边界,这样您就不会意外地在较长的参数名称中匹配较短的参数名称。

另外,如果将标量值强制转换为一个条目的数组,则不需要特殊情况的数组:

preg_replace("/:$Name\b/", 
    implode(",", $this->Adapter->QuoteValue( (array) $Parameter['Value'] )), 
    $Statement);

但是请注意,当标识符或字符串文字包含看起来像参数占位符:

SELECT * FROM ":Name";

SELECT * FROM Table WHERE column = ':Name';

当带引号的标识符和字符串文字可以包含转义引号时,这会变得更加复杂。

SELECT * FROM Table WHERE column = 'word\':Name';

您可能需要重新考虑在准备期间将变量插入 SQL 字符串,因为您正在破坏准备好的语句在安全性或性能方面的任何优势。

我明白你为什么要做你正在做的事情,因为并非所有 RDBMS 后端都支持命名参数,而且 SQL 参数也不能用于 IN() 谓词中的值列表。但你正在创建一个非常漏洞百出的抽象。

You should use the \b metacharacter to match the word boundary, so you don't accidentally match a short parameter name within a longer parameter name.

Also, you don't need to special-case arrays if you coerce a scalar Value to an array of one entry:

preg_replace("/:$Name\b/", 
    implode(",", $this->Adapter->QuoteValue( (array) $Parameter['Value'] )), 
    $Statement);

Note, however, that this can make false positive matches when an identifier or a string literal contains a pattern that looks like a parameter placeholder:

SELECT * FROM ":Name";

SELECT * FROM Table WHERE column = ':Name';

This gets even more complicated when quoted identifiers and string literals can contain escaped quotes.

SELECT * FROM Table WHERE column = 'word\':Name';

You might want to reconsider interpolating variables into SQL strings during prepare, because you're defeating any benefits of prepared statements with respect to security or performance.

I understand why you're doing what you're doing, because not all RDBMS back-end supports named parameters, and also SQL parameters can't be used for lists of values in an IN() predicate. But you're creating an awfully leaky abstraction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文