【问题标题】:filter_var versus preg_matchfilter_var 与 preg_match
【发布时间】:2009-10-09 14:40:31
【问题描述】:

早安

我正在将我正在开发的网站转换为与最新版本的 PHP 兼容,因此我正在检查所有 ereg 实例并将其替换为未折旧的等价物。然而,有人告诉我有一个方便的 PHP 内置函数,称为 filter_var。

我的问题是,使用 filter_var 而不是 preg_match 是否有意义?例如,选择其中一个是否有性能提升或任何其他好处,如果有,它们是什么?

【问题讨论】:

  • 您能否提供一个您将重构的示例代码?据我所知,filter_var 与正则表达式无关。
  • @IvanNevostruev 他正在谈论验证过滤器,FILTER_VALIDATE_REGEXP 用于 PHP 过滤器功能。 php.net/manual/en/filter.filters.validate.php

标签: php regex


【解决方案1】:

首先,关于过滤的 PHP 手册页:https://php.net/manual/en/book.filter.php

第二,上下文是关键。一般来说,过滤器函数被设计为使用外部输入(标量或数组),或内部输入。外部输入来自 HTTP 请求/PHP 引擎或表单提交等来源。

带有filter_input 前缀的过滤函数允许您完全绕过 $_SERVER、$_COOKIE、$_POST 和 $_GET 超全局变量。尽管您通常会指定要从“哪里”获取数据,但过滤函数并没有明确地使用 $_POST、$_GET、$_COOKIE 和 $_SERVER。您对变量/数组元素所做的更改不会在 $_GET、$_POST 或 $_SERVER 中显示,因此以这种方式使用过滤器是一种范式转变,可能会显着改变应用程序的流程。换句话说,您必须自己跟踪外部输入。我这样做是为了对外部输入进行初始清理(剥离、替换、更改等)。我根本不再使用 $_POST、$_GET 或 $_SERVER。虽然,我仍然使用 $_FILES。

filter_var 为前缀的函数用于过滤程序中已经存在的任何通用数组。我在使用filter_input 后使用它。您可以在这两种情况下使用许多过滤器,但您的问题是关于性能

如果您选择将FILTER_VALIDATE_REGEXP 过滤器与任何过滤功能一起使用,我无法想象这种间接方法比直接使用preg_match() 更有效。就其他过滤器而言,如果它们只是从正则表达式调用中删除了“n”个方法/函数,我也看不到那里的效率提高

我认为过滤器功能旨在帮助提高跨多个应用程序发生的过滤任务的一致性。它们可能没有被设计为更高效,但它们绝对被设计为比正则表达式更可访问(尽管我非常擅长正则表达式)。我更喜欢直接了解正在发生的事情,但有些人不关心或可能不太关心。但是,过滤器功能为不了解正则表达式和其他基本 Web 应用程序安全流程的人打开了过滤字符串的大门。

当然,不使用过滤功能也可以。

更重要的是,我将过滤器函数与我自己的 sanitizer 和 validator 类结合使用。所以,我不是要求 PHP 为我考虑,我只是用它来增强我已经知道如何做的事情(以防他们的函数得到我想念的东西)。纵深防御。

总而言之,您最好的选择就是使用preg_match(),除非您打算更改应用程序的输入流filter_input 函数)。即使这样,也不会提高性能,但您可以绕过 $_SERVER、$_POST 和 $_GET。此外,您可以利用更简单、结构化、一致的过滤功能,并能够使用回调函数 (FILTER_CALLBACK) 调用自定义的内部方法/函数(我也这样做)。此外,您仍然可以使用您自己的正则表达式和使用FILTER_VALIDATE_REGEXP 过滤器的过滤器函数,但我认为没有理由相信如果您这样做,您的应用程序的性能会提高。可维护性?也许。这取决于编写代码的人。

【讨论】:

    【解决方案2】:

    filter_var — 使用指定的过滤器过滤变量
    preg_match — 执行正则表达式匹配

    我想 use 可以使用 filter_var 来过滤变量,但作为 preg_match 的替代品,我认为从 ereg 升级不是一个好主意,因为 filter_var 不使用正则表达式,你必须重写很多功能/这样做的逻辑。

    【讨论】:

    • 我的立场是正确的,就像我认为它对它使用的各种项目所做的那样。
    • 澄清一下:PHP 的 filter_var() 函数在内部使用正则表达式来执行验证。请参阅 PHP 源代码以验证这一点:github.com/php/php-src/blob/master/ext/filter/…
    • @AmalMurali 您的意思是您可以选择将FILTER_VALIDATE_REGEXP 过滤器与filter_var() 一起使用,但据我所知filter_var() 没有默认的内部正则表达式功能。 filter_var() 背后的代码可能是真的使用正则表达式来验证字符串的长度(等等)。使用filter_var() 很可能是使用正则表达式的一种高度间接的方式。我相信这些功能背后的动机是尝试建立一致性(以抽象的方式),因为过滤是许多应用程序中执行的常见任务。
    • @AnthonyRutledge:OP 询问是否有一个性能提升比另一个,我只是澄清两者都使用相同的底层技术来执行任务(即正则表达式),所以有不会有太大的不同。唯一的区别是它在更粗略的水平上(PHP 的实现) - 它可能会快一点。
    【解决方案3】:

    切换到使用filter_var() 实际上是个好主意。您将无法使用现有的正则表达式,但是您可以完全消除它们。通常,我们在应用程序中使用的正则表达式仅用于简单的validations 和过滤,这正是filter_var() 函数的用途。

    例如,在您的代码中,您可能已经有:

    if (eregi('\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b', $_POST['email'])) {
        echo "valid";
    }
    

    这可以替换为更漂亮的版本(不依赖于自定义正则表达式):

    if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
        echo "valid";
    }
    

    filter_var() 函数还能够sanitize 输出您正在检查的特定数据不需要的字符,并返回清理后的字符串(而不是布尔值):

    $clean = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
    

    这种与filter_var() 的用法将取代ereg_replace() 类型的函数。

    但是,对于最简单的升级,您只需在 ereg*() 系列函数前加上一个“p”,这使得它们符合 PCRE(因此在 PHP 5.3+ 中不再被弃用)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多