【问题标题】:PHP is_numeric or preg_match 0-9 validationPHP is_numeric 或 preg_match 0-9 验证
【发布时间】:2011-11-30 18:35:43
【问题描述】:

这对我来说不是什么大问题(据我所知),这更像是我感兴趣的事情。但是,使用is_numeric 而不是preg_match(反之亦然)来验证用户输入值的主要区别是什么?

示例一:

<?php
    $id = $_GET['id'];
    if (!preg_match('/^[0-9]*$/', $id)) {
        // Error
    } else {
        // Continue
    }
?>

示例二:

<?php
    $id = $_GET['id'];
    if (!is_numeric($id)) {
        // Error
    } else {
        // Continue
    }
?>

我假设两者的作用完全相同,但是否有任何特定差异可能会在以后以某种方式导致问题?有没有“最好的方法”或我没有看到的东西让它们与众不同。

【问题讨论】:

    标签: php validation preg-match isnumeric


    【解决方案1】:

    如果您检查它是否是一个数字,is_numeric() 在这里要好得多。它比正则表达式更具可读性和速度。

    你的正则表达式的问题是它不允许十进制值,所以基本上你只是在正则表达式中写了is_int()。仅当您的输入中存在非标准数据格式时才应使用正则表达式; PHP 有很多内置的验证函数,甚至是email validator without regex

    【讨论】:

    • 我不认为is_int() 做你认为它做的事——它实际上检查被检查变量的类型;它不是字符串验证器。
    【解决方案2】:

    is_numeric 将接受“-0.5e+12”作为有效 ID。

    【讨论】:

      【解决方案3】:

      不完全一样。

      来自 is_numeric 的 PHP 文档:

      '42' is numeric
      '1337' is numeric
      '1e4' is numeric
      'not numeric' is NOT numeric
      'Array' is NOT numeric
      '9.1' is numeric
      

      使用您的正则表达式,您只检查“基本”数值。

      另外is_numeric() 应该更快。

      【讨论】:

      • 因此使用is_numeric 来检查论坛上的帖子条目,这些条目都具有由auto_increment 分配的唯一ID,这可能会导致问题,因为数据库只有整数,没有小数,符号等
      • @Joe Mottershaw:如果是这样,你会使用is_int()
      • @JoeMottershaw: 或者你最好把它转换成一个整数:$id = (int) $_REQUEST['id'];
      【解决方案4】:

      is_numeric() 允许任何形式的数字。所以13.141592652.71828e10 都是“数字”,而您的正则表达式归结为相当于is_int()

      【讨论】:

      • 不确定 11 年它是如何工作的。但是现在 is_intis_integer 实际上对于任何给定的字符串都返回 false
      【解决方案5】:

      is_numeric 检查更多:

      查找给定变量是否为数字。数字字符串包括 可选符号、任意位数、可选小数部分和 可选指数部分。因此 +0123.45e6 是一个有效的数值。 也允许使用十六进制表示法 (0xFF),但只能不带符号, 小数和指数部分。

      【讨论】:

        【解决方案6】:

        is_numeric() 测试值是否为数字。但它不一定必须是整数 - 它可以是十进制数或科学记数法中的数字。

        您给出的preg_match() 示例仅检查值是否包含数字0 到9;任意数量,任意顺序。

        请注意,您给出的正则表达式也不是一个完美的整数检查器,就​​像您编写它的方式一样。它不允许负面因素;它确实允许长度为零的字符串(即根本没有数字,这可能不应该是有效的?),它允许数字有任意数量的前导零,这又可能不是预期的。

        [编辑]

        根据您的评论,更好的正则表达式可能如下所示:

        /^[1-9][0-9]*$/
        

        这会强制第一个数字仅介于 1 和 9 之间,因此您不能使用前导零。它还强制它至少为一位数字长,因此解决了零长度字符串问题。

        你不担心负面因素,所以这不是问题。

        您可能希望限制位数,因为就目前情况而言,它将允许太大而无法存储为整数的字符串。要限制这一点,您可以将星号更改为长度限制,如下所示:

        /^[1-9][0-9]{0,15}$/
        

        这将允许字符串长度在 1 到 16 位之间(即第一个数字加上 0-15 个其他数字)。随意调整花括号中的数字以满足您自己的需要。如果你想要一个固定长度的字符串,那么你只需要在大括号中指定一个数字。

        希望对您有所帮助。

        【讨论】:

        • 那么使用正则表达式,您将如何纠正前导零等问题?毕竟这可能会给我带来问题,因为这是我一直在使用的方法。如果我只是想验证它是一个整数(4,8,15,16,23,42,108 等),没有前导零,没有小数点,没有负数,这将如何实现?
        • 谢谢 Spudley,这是一个非常清楚的解释 - 肯定对他们的差异有更好的理解。看起来我会回去调整我的一些代码! :)
        • @Spudley,十进制值应该使用什么?
        • @er.irfankhan11:答案取决于您要允许的小数位数等。提示:使用\.[.] 作为小数点,以及类似的规则上面是它后面的数字。如果您需要更多详细信息,请作为单独的问题提出。
        • 可能是我在论坛上见过的最好的解释之一。直到今天,我都在使用正则表达式。这对我来说是胡言乱语!我见过人们用正则表达式帮助别人,但他们通常缺乏解释。感谢这个可靠的答案。现在我不必再被他们吓倒了。谢谢!
        【解决方案7】:

        根据http://www.php.net/manual/en/function.is-numeric.php,is_numeric 允许类似“+0123.45e6”或“0xFF”。我认为这不是您所期望的。

        preg_match 可能很慢,您可以使用 0000 或 0051 之类的内容。

        我更喜欢使用 ctype_digit(仅适用于字符串,可以使用 $_GET)。

        <?php
          $id = $_GET['id'];
          if (ctype_digit($id)) {
              echo 'ok';
          } else {
              echo 'nok';
          }
        ?>
        

        【讨论】:

        • 所以ctype_digit 只检查四舍五入的数字,如果它是正数还是负数呢?它是如何工作的?
        • 它只适用于正数,我认为它对 id 很有用(我的代码中没有负 Id): var_dump(ctype_digit('-5')); // 返回错误
        • 我也可能会使用ctype_digit() 来完成这项任务。不过,我应该注意,ctype_digit() 将允许00000004;因此,如果您不希望零左填充成为可能,您可以将 $id = (int)$id 显式转换为 int(在 ctype_digit() 检查之后)。
        【解决方案8】:

        is_numeric 检查它是否是任何类型的数字,而您的正则表达式检查它是否是整数,可能带有前导 0。对于存储为整数的 id,我们很可能不希望有前导 0。按照 Spudley 的回答,我们可以这样做:

        /^[1-9][0-9]*$/
        

        但是,正如 Spudley 所指出的,生成的字符串可能太大而无法存储为 32 位或 64 位整数值。带符号的 32 位整数的最大值为 2,147,483,647(10 位),带符号的 64 位整数的最大值为 9,223,372,036,854,775,807(19 位)。但是,许多 10 位和 19 位整数分别大于最大 32 位和 64 位整数。一个简单的纯正则表达式解决方案是:

        /^[1-9][0-9]{0-8}$/ 
        

        /^[1-9][0-9]{0-17}$/
        

        分别,但是这些“解决方案”不幸地将每个解决方案限制为 9 位和 19 位整数;几乎没有令人满意的结果。更好的解决方案可能是这样的:

        $expr = '/^[1-9][0-9]*$/';
        if (preg_match($expr, $id) && filter_var($id, FILTER_VALIDATE_INT)) {
            echo 'ok';
        } else {
            echo 'nok';
        }
        

        【讨论】:

          【解决方案9】:

          PHP 的is_numeric 函数允许浮点数和整数。同时,如果要验证表单数据(仅限字符串),is_int 函数过于严格。因此,您通常最好为此使用正则表达式。

          严格来说,整数是正负整数,也包括零。这是一个正则表达式:

          /^0$|^[-]?[1-9][0-9]*$/

          或者,如果你想允许前导零:

          /^[-]?[0]|[1-9][0-9]$/

          请注意,这将允许使用诸如 -0000 之类的值,但这不会在 PHP 中引起问题。 (MySQL 也会将这些值转换为 0。)

          出于32/64-bit PHP platform features 和/或数据库兼容性的考虑,您可能还希望限制整数的长度。例如,要将整数的长度限制为 9 位(不包括可选的 - 符号),您可以使用:

          /^0$|^[-]?[1-9][0-9]{0,8}$/

          【讨论】:

          • 在我的项目中,我从没想过“id”会为零。
          【解决方案10】:

          同时,以上所有值只会将值限制为整数, 所以我用

          /^[1-9][0-9\.]{0,15}$/
          

          也允许浮点值。

          【讨论】:

            【解决方案11】:

            您可以使用此代码进行号码验证:

            if (!preg_match("/^[0-9]+$/i", $phone)) {
                    $errorMSG = 'Invalid Number!';
                    $error    = 1;
                }
            

            【讨论】:

            • 为什么你需要一个完全数字字符类的不区分大小写的标志?你能给我看一个大写数字和小写数字的例子吗?
            【解决方案12】:

            您可以使用 filter_var() 来检查字符串中的整数

            <?php
            $intnum = "1000022";
            if (filter_var($intnum, FILTER_VALIDATE_INT) !== false){
                echo $intnum.' is an int now';
            }else{
                echo "$intnum is not an int.";
            }
            // will output 1000022 is an int now
            

            【讨论】:

              猜你喜欢
              • 2014-01-20
              • 1970-01-01
              • 2023-04-08
              • 1970-01-01
              • 1970-01-01
              • 2011-07-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多