2011-10-04 62 views
30

这对我来说不是一个大问题(据我所知),它更多的是我感兴趣的东西。但是,使用is_numeric而不是preg_match(反之亦然)来验证用户输入值有什么主要区别(如果有的话)。PHP is_numeric或preg_match 0-9验证

例一:

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

例二:

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

我认为两者不完全一样,但有可能导致问题以后就任何具体的区别是什么?有没有一种“最好的方式”,或者我没有看到哪种让他们与众不同的东西。

回答

49

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

preg_match()您只给出了一个例子,检查值是否包含数字0到9;它们中的任意数量,以及任何顺序。

请注意,您给出的正则表达式也不是一个完美的整数检查器,就​​像你写的那样。它不允许否定;它确实允许一个零长度的字符串(即根本没有数字,这大概不应该是有效的?),并且它允许该数字具有任意数量的前导零,这也可能不是预期的。

[编辑]

根据您的意见,更好的正则表达式可能是这样的:

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

这迫使第一位数只能是1和9之间,所以你不能有前导零。它也迫使它至少有一位数字,所以解决了零长度字符串问题。

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

您可能想要限制数字的数量,因为按照现状,它将允许太大的字符串不能存储为整数。要限制这一点,你会改变恒星成长度限制像这样:

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

这将使字符串是数字1和16之间的长(即第一个数字加0-15更多的数字)。随意调整花括号中的数字以适应您自己的需求。如果你想要一个固定长度的字符串,那么你只需要在大括号中指定一个数字。

希望有所帮助。

+0

所以用正则表达式你会如何纠正前导零等问题?这可能会给我带来问题,因为这是我一直在使用的方法。如果我只是想验证它是一个整数(4,8,15,16,23,42,108等),没有前导零,没有小数点,没有负数,这将如何实现? – Joe

+0

@JoeMottershaw - 我将编辑答案以添加更多信息.... – Spudley

+0

谢谢Spudley,这是一个非常明确的解释 - 绝对能更好地理解他们的差异。看起来我会回去调整我的一些代码! :) – Joe

1

如果你只检查如果它是一个数字,is_numeric()很多更好地在这里。它比正则表达式更可读,更快捷。

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

+0

我不认为'is_int()'做什么你认为它 - 它实际上检查的变量正在检查的类型;它不是一个字符串验证器。 – Spudley

4

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

5

不完全一样。

从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()应该更快。

+0

因此,使用'is_numeric'来检查论坛上的帖子条目,它们都具有由'auto_increment'指定的唯一ID,由于数据库只有整数,无小数,符号等,因此可能会导致问题 – Joe

+0

@Joe Mottershaw:if你可以使用'is_int()' – PeeHaa

+0

@JoeMottershaw:或者更好的方法是将其转换为int:'$ id =(int)$ _REQUEST ['id'];' – PeeHaa

7

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

+0

不确定它是如何工作的' 11。但是现在'is_int'和'is_integer'实际上对任何给定的字符串都返回false – cvsguimaraes

3

is_numeric检查更等价的:

求给定变量是否是数字。数字字符串包括可选符号 ,任意数字位数,可选小数部分和可选指数部分 。因此+ 0123.45e6是一个有效的数值。 十六进制符号(0xFF)也是允许的,但只有没有符号, 十进制和指数部分。

10

根据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'; 
    } 
?> 
+0

所以'ctype_digit'只是检查四舍五入的数字,那么如果它是一个正数或负数呢?它如何工作? – Joe

+0

它只适用于正数,我认为它可以用于一个id(我的代码中没有负面的ID): var_dump(ctype_digit(' - 5')); //返回false –

5

is_numeric检查它是否是任何种类的数量,而你的正则表达式检查它是否是一个整数,可能与前导零。对于一个存储为整数的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'; 
} 
1

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

严格地说,整数是整数正数和负数,也包括零。以下是此正则表达式:

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

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

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

注意,这将允许值,例如-0000? ,这在PHP中不会导致问题,h H但是。 (MySQL也会将这样的值转换为0.)

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

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

0

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

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

以允许浮点值太。

0

您可以使用数字验证验证码:

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