【问题标题】:PHP/RegEx - Logic for prepending table namesPHP/RegEx - 预先表名的逻辑
【发布时间】:2009-01-17 20:31:59
【问题描述】:

所以我正在尝试构建一个脚本,该脚本会自动在有效列名前面加上适当的表前缀(例如“t.”或“r.”)

$t_columns = array('id', 'name', 'label');
$r_columns = array('related_value');

输入:

id > 1 AND (name = 'Hello' OR label IN ('World', 'Planet name AND label')) AND (related_value > 1 AND related_value < 50)

输出:

t.id > 1 AND (t.name = 'Hello' OR t.label IN ('World', 'Planet name AND label')) AND (r.related_value > 1 AND r.related_value < 50)

请注意您无法执行正常的 str_replace。什么是最简单的代码(我猜是 preg_replace)来确保所有表名都被正确地添加?

【问题讨论】:

  • 请问上面INPUT之类的SQL是从哪里来的?创建SQL的时候可以不加表前缀吗,还是不能这样?
  • 这是一个函数,例如buildRecords($where = 1, $orderby = 'id DESC')。用户无需知道表前缀即可添加 $where 字符串。所以不,它完全是动态的。
  • 用户可以输入包含他们喜欢的任何文本的 WHERE 子句吗?如果我误解了您,我深表歉意,但这对我来说似乎存在 SQL 注入风险。
  • 是的。问题是只有登录的管理员才能构建 $where 查询。

标签: php regex logic


【解决方案1】:

经过几秒钟的思考,这是我的解决方法:

逐个字符地遍历字符串,查找单引号,但跳过转义字符。两个未转义的单引号(即字符串)之间的内容将被替换为唯一标记,并放入关联数组中,该标记作为键,原始字符串作为值。

现在我们已经排除了字符串,对已知的列名执行str_replace()(或preg_replace(),如果您坚持的话)。我可能会将列名构造成一个关联数组,表的别名作为键,值作为包含列名的枚举数组。这样,替换可以自动进行。

填写完表名后,只需对标记执行str_replace(),将原始字符串替换回原位即可。

我敢肯定,有人可能会使用一个超级棒(而且可能几乎无法维护)的正则表达式一键完成所有这些操作。但我更喜欢仅在正则表达式实际上是正确工具的情况下使用正则表达式,而不是 CFL 更适合的情况。

【讨论】:

  • 所以基本上,A) 用某种随机键替换单引号内的所有文本,B) 使用 str_replace 替换表名,C) 用原始文本替换键...跨度>
  • 如果 SQL 包含带有不匹配且未转义的单引号字符的注释,则此方法将不起作用。
  • 马特,这是一个很棒的简报:)。 Pourquoi:可以从解析的查询中完全删除评论。
【解决方案2】:

这可以通过多种方式完成,也可以使用正则表达式。我个人会使用数组方法。首先,我会这样定义修饰表:

$table = array(
    'id' => 't.id',
    'name' => 't.name',
    'label' => 't.label',
    'related_value' => 'r.related_value'
);

这将使 str_replace() 调用更容易:

function mangling(&$v, $k, $table)
{
    if (($k & 1) == 0)
        $v = str_replace(array_keys($table), array_values($table), $v);
}

$spans = explode("'", ' ' . $input);
array_walk($spans, 'mangling', $table);
$output = implode("'", $spans);

【讨论】:

    【解决方案3】:

    我不知道在这里使用正则表达式是否是个好主意。我会说在 PHP 中自己执行验证是值得的。然后,如果您的数据库需要任何更改,您就不必担心如何提高正则表达式的稳健性。

    正如 Jamie Zawinski 曾经说过的,“有些人在遇到问题时会想‘我知道,我会使用正则表达式。’现在他们有两个问题。”

    在创建可确保您使用正确的数据库的工作流方面,我会考虑采用面向对象的方法。 T 和 R 表的类可以是模型类的实例化子类,该模型类负责在同一方法中使用条件逻辑而不是正则表达式来构建正确的表类型对象。

    【讨论】:

    • 恭喜,您的最后一段获得了“最具技术术语”奖。从前两段来看,我认为你同意 wolfie...
    • “做一个可以为你做一件事或另一件事的东西,这样你就不会自己搞砸了”。更好?
    猜你喜欢
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    相关资源
    最近更新 更多